Unit test case for uploading file using nunit C# - c#

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.

Related

c# UnitTesting Test that API call was made

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

Define header for upload file in API

I am trying to upload excel file to convert it to Json, but i need to passing through API Gateway. I have problem to passing the file from API Gateway.
I try to set header in ContentDisposition, ContentLength and ContentType manually.
using (var client = new HttpClient())
{
using (var Content = new MultipartFormDataContent())
{
var name = Path.GetFileName(postedFile.FileName);
HttpContent content = new StringContent("");
content.Headers.Clear();
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = name,
FileName = name
};
content.Headers.Add("Content-Length", postedFile.ContentLength.ToString());
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data");
Content.Add(content);
}
HttpResponseMessage reply = new HttpResponseMessage();
reply = await client.GetAsync(#"http://localhost:60897/api/ExceltoJSONConversion");
if (reply.IsSuccessStatusCode)
{
var responseString = await reply.Content.ReadAsStringAsync();
return Json(JsonConvert.DeserializeObject(responseString));
}
}
I have been tried several code but reply always return code 405 MethodNotAllowed.
here my controller where i proceed file
[HttpPost]
[Route("api/ExceltoJSONConversion")]
public IHttpActionResult ExceltoJSONConversion()
{
// Process the file from API Gateway
}
Am i missing something when define Header multipart/form-data? or my code just a mess?
Your API method accepts POST requests only ([HttpPost] attribute).
And in your client you are trying to get API through GET method (client.GetAsync ... ).
Either decorate your API method with [HttpGet] instead of [HttpPost], either change client part to use POST (client.PostAsync ... ).

How to consume .NET Core FileContentResult in an httpClient test method

I have a .NET Core 2.2 API Controller method that returns a FileContentResult like so:
[HttpGet]
public async Task<IActionResult> Get()
{
return File(_service.GetCsvFile(), "text/csv", "results.csv");
}
Also, I have an integration test that uses a WebHostFixture and httpClient to get the results. However, the content is always empty, whatever method I try. While there is a file with content being returned:
var response = await WebHost.Client.GetAsync(url, HttpCompletionOption.ResponseContentRead);
var result = await response.Content.ReadAsByteArrayAsync();
Also, when I do the following, no content is being read:
var response = await WebHost.Client.GetByteArrayAsync(url);
All other integration tests using this WebHostFixture run successful, so it seems this is the only endpoint that is not returning its data properly in my test environment. When I call the endpoint using Postman, a CSV file with content is being returned properly.
Also, in Postman, besides receiving the binary data in the body, the following headers are returned:
However, in my test method, after calling the GetAsync method, the
response.Content.Headers.ContentType is "text/csv", but the response.Content.Headers.ContentLength is 0.
What am I doing wrong and why is there no binary data being returned here?
Try this:
byte[] BytesResult = await httpClient.GetByteArrayAsync("YourRequestUri").ConfigureAwait(false);
Convert it to string and compare the result. It works great with approval tests.
Example:
var result = fileresult as FileContentResult;
byte[] buffer = result.FileContents;
string s = System.Text.Encoding.UTF8.GetString(buffer, 0, buffer.Length);
When reading a file you need to use GetStreamAsync
Example:
using (var csvStream = await WebHost.Client.GetStreamAsync(url))
{
// Do something with stream contents.
}

Send a 'Stream' over a PutAsync request

I'm trying my hand at .NET Core but I'm stuck trying to convert multipart/form-data to an application/octet-stream to send via a PUT request. Anybody have any expertise I could borrow?
[HttpPost("fooBar"), ActionName("FooBar")]
public async Task<IActionResult> PostFooBar() {
HttpResponseMessage putResponse = await _httpClient.PutAsync(url, HttpContext.Request.Body);
}
Update: I think I might have two issues here:
My input format is multipart/form-data so I need to split out the file from the form data.
My output format must be application-octet stream but PutAsync expects HttpContent.
I had been trying to do something similar and having issues. I needed to PUT large files (>1.5GB) to a bucket on Amazon S3 using a pre-signed URL. The implementation on Amazon for .NET would fail for large files.
Here was my solution:
static HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(60);
static async Task<bool> UploadLargeObjectAsync(string presignedUrl, string file)
{
Console.WriteLine("Uploading " + file + " to bucket...");
try
{
StreamContent strm = new StreamContent(new FileStream(file, FileMode.Open, FileAccess.Read));
strm.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
HttpResponseMessage putRespMsg = await client.PutAsync(presignedUrl, strm);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
return true;
}
Turns out Request has a Form property that contains a Files property that has an OpenReadStream() function on it to convert it into a stream. How exactly I was supposed to know that, I'm not sure.
Either way, here's the solution:
StreamContent stream = new StreamContent(HttpContext.Request.Form.Files[0].OpenReadStream());
HttpResponseMessage putResponse = await _httpClient.PutAsync(url, stream);

How to create a response message and add content string to it in ASP.NET 5 / MVC 6

In web api 2 we used to do this to get a response with string content:
var response = Request.CreateResponse(HttpStatusCode.Ok);
response.Content = new StringContent("<my json result>", Encoding.UTF8, "application/json");
How can you acheive the same in ASP.NET 5 / MVC 6 without using any of the built in classes like ObjectResult?
You can write to the Response.Body stream directly (as the Body is a plain old System.IO.Stream) and manually set content type:
public async Task ContentAction()
{
var jsonString = "{\"foo\":1,\"bar\":false}";
byte[] data = Encoding.UTF8.GetBytes(jsonString);
Response.ContentType = "application/json";
await Response.Body.WriteAsync(data, 0, data.Length);
}
You could save yourself some trouble using some utilities from Microsoft.AspNet.Http:
The extension method WriteAsync for writing the string contents into the response body.
The MediaTypeHeaderValue class for specifying the content type header. (It does some validations and has an API for adding extra parameters like the charset)
So the same action would look like:
public async Task ContentAction()
{
var jsonString = "{\"foo\":1,\"bar\":false}";
Response.ContentType = new MediaTypeHeaderValue("application/json").ToString();
await Response.WriteAsync(jsonString, Encoding.UTF8);
}
In case of doubt you can always have a look at the implementation of ContentResult and/or JsonResult.

Categories

Resources