I am writing unit test for a simple function
public async Task<HttpResponseMessage> MakeRestCallAsync(Uri uri, string input)
{
using (httpClient = new HttpClient())
{
using (var formData = new MultipartFormDataContent())
{
//add content to form data
formData.Add(new StringContent(input), "Input");
return await httpClient.PostAsync(uri, formData);
}
}
}
I would like to test that httpClient fired the PostAsync
I am using Microsoft.VisualStudio.TestTools.UnitTesting for the test project
Can't find a proper way to do that
Also if possible I would like to test that the call was actually made with the passed URI and passed input
Related
I am writing some unit test to check my end points of webservice. Fortunately I write some of the test cases for get/post request and it works fine except the one.
I want to write the test case to check the file uploading method of webservice. The webservice endpoint on PostMan is :
The body of the request takes userID and fileUpload attribute.
I write the basic code for this but don't know how to pass the form data as request body in Nunit test case.
private HttpClient _client;
[Test]
public async Task UploadPDFfile()
{
var response = await _client.PostAsync("http://localhost:5000/documents/");
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
Can anyone please tell me how I can pass the form-data attribute in PostAsync method in Nunit testing C# to check the file upload functionality.
I like to use foo files in this kind of test.
HttpClient.PostAsync() has a parameter called content.
You should create a HttpContent instance and send it with the post method:
var filePath = "yourFooFilePathHere";
using (var fs = File.OpenRead(filePath))
using (var fileContent = new StreamContent(fs))
{
var content = new MultipartFormDataContent
{
{ fileContent, "file", yourFileName }
};
content.Add(new StringContent(userId.ToString(), Encoding.UTF8, "application/json"));
var response = await _client.PostAsync("http://localhost:5000/documents/", content);
}
Please notice that I'm passing the created HttpContent as a parameter for the PostAsync method.
I have an existing and functioning API, which now have to be able to get data from another external API. How do i do that best?
I have tried with using HTTPClient, but i can't seem to get it to work. The error i get:
"No MediaTypeFormatter is available to read an object of type 'IList`1' from content with media type 'text/html'." -> I get this error on line 37. Can you spot it and/or tell me how I can do this differently, taking into account that all i want is the data (From the external API) and not to display it using a view, as this is an API?
Code below. I have also created a Pastebin: https://pastebin.com/MuKjEVys
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net;
namespace API.Controllers
{
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ExternalApiController : Controller
{
private string ExternalApiLink = "https://blablabla.com/api";
private string ExternalApiLinkGet = "/module/1/";
[HttpGet("getdata")]
public ActionResult<ExternalApi> GetDataFromExternal()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(ExternalApiLink);
var requestApi = client.GetAsync(ExternalApiLinkGet);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "XXXX");
requestApi.Wait();
var resultFromApi = requestApi.Result;
if (resultFromApi.IsSuccessStatusCode)
{
var readResponse = resultFromApi.Content.ReadAsAsync<IList<ExternalApi>>();
readResponse.Wait();
var data = readResponse.Result;
return Json(data);
}else
{
return NotFound();
}
}
}
}
}
Your response content seems to be json, while the content-type is text/html. If that is the case, the first thing to do would be to call the party that is exposing the service and have them fix it. In the meantime you could just read the content of the response as a string, and deserialize that string:
// Note that I made this method async.
public async Task<IActionResult> GetDataFromExternal()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(ExternalApiLink);
// note that I moved this line above the GetAsync method.
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "XXXX");
// note that I'm disposing the response
using (var response = await client.GetAsync(ExternalApiLinkGet))
{
if (response.IsSuccessStatusCode)
{
// Since the response content is json, but the content-type
// is text/html, simply read the content as a string.
string content = await response.ReadAsStringAsync();
// You can return the actual received content like below,
// or you may deserialize the content before returning to make
// sure it is correct, using JsonConvert.DeserializeObject<List<ExternalApi>>()
// var data = JsonConvert.DeserializeObject<List<ExternalApi>>(content);
// return Json(data);
return Content(content, "application/json");
}
else
{
return NotFound();
}
}
}
}
I have an API which has to do the following:
Incoming HttpRequest -> Logic to decide which endpoint -> Send call to specific endpoint (another API)
HttpResult -> Logic to manipulate response -> Send response back
I was wondering whether there is a clean way to do so? Currently using something like this:
var httpRequestMessage = new HttpRequestMessage()
{
Method = new HttpMethod(Request.Method),
RequestUri = new Uri(endpoint)
};
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", Request.Headers["Authorization"][0]);
using (var response = await httpClient.SendAsync(httpRequestMessage))
{
using (HttpContent content = response.Content)
{
string data = await content.ReadAsStringAsync();
}
}
}
But I'm not really happy about the conversion from HttpRequest to HttpRequestMessage. I'd just like to pass the HttpRequest with another Uri but still be able to put logic in between the requesting and receiving.
When working with proxy middleware are you still able to put logic in between the request and result?
I'm trying to send an object using Web-APi 2 and protobuf-net. I keep getting a 404 error so I assume something goes wrong with the routing?
When I comment out the serialize line
ProtoBuf.Serializer.Serialize(memstream, package);
(so the memory stream stays empty) the routing works and RecievePackage is called. And the package parameter is empty. (the package object itsself is not NULL but all it's properties are.)
Whenever the memory stream is not empty I get a 404 error. What am I doing wrong here?
Receive code:
[Route("Receive")]
[HttpPost]
public async Task<IHttpActionResult> RecievePackage(PackageModel package)
{
id = await SavePackage(package);
return Created("", id);
}
Send code:
private async Task SyncUpAsync(string apiUrl, PackageModel package)
{
using (HttpClient client = new HttpClient())
using (var memstream = new MemoryStream())
{
var uri = new Uri(new Uri(ApiUrl), apiUrl);
ProtoBuf.Serializer.Serialize(memstream, package);
memstream.Position = 0;
var content = new StreamContent(memstream);
content.Headers.Add("SyncApiToken", ApiKey);
content.Headers.Add("Content-Type", "application/x-protobuf");
var response = await client.PostAsync(uri, content);
}
}
I have a Portable Class Library (PCL) method like this:
public async Task<string> GetLineStatuses()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
{
return response.GetResponseStream().ReadAllText();
}
}
My ASP.NET Web Api method looks like this:
public async Task<HttpResponseMessage> Get()
{
HttpResponseMessage response = new HttpResponseMessage();
string statuses = await service.GetStatuses();
response.Content = new StringContent(statuses);
return response;
}
What are the implications of returning a Task in Web API. Is this allowed? The only reason I want to use await is so I can use a Portable Class Library (PCL). What is the best practice? Should I have a syncronous version of my method and an asyncronous version? What are the performance and code readability and maintainability implications?
Also would I have the same effect if I returned Task<string> rather than Task<HttpResponseMessage>?
Async and await are perfectly acceptable in ASP.NET. Here's a Scott Handselman video demoing it: http://www.asp.net/vnext/overview/aspnet/async-and-await
"Also would I have the same effect if I returned Task<string> rather than Task<HttpResponseMessage>?"
Not really sure what you mean by this. The Task is like a container for the object, so a Task<string> would contain your string result and a Task<HttpResponseMessage> would contain your HttpResponseMessage result... Is that what you mean? I think either method is perfectly acceptable. If you just need the string, then go with that. No point in returning more than you need.
as alternative:
public static async Task<string> CallGET(string requestUri, string id = "")
{
string responseData;
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Uri.TryCreate(new Uri(baseURI), $"{requestUri}{(string.IsNullOrEmpty(id) ? string.Empty : $"/{id}")}", out Uri fullRequestUri);
using (var response = await client.GetAsync(fullRequestUri))
{
responseData = await response.Content.ReadAsStringAsync();
}
return responseData;
}
}
and call would be:
var getListUsersResult = Utils.CallGET($"/v1/users").Result;
var resultset= JsonConvert.DeserializeObject(getListUsersResult, typeof(List<UsersDTO>)) as List<UsersDTO>;
UserDTO r = users.Where(d => d.Name.ToLower().Contains("test")).FirstOrDefault();
and another call for one item:
var getUser = Utils.CallGET($"/v1/users", $"{USER_ID}").Result;
var getUserResponse = JsonConvert.DeserializeObject(getUser, typeof(UserDTO)) as UserDTO;