Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a mulitpart/mixed form request in unit test

I am working on a Web API endpoint which will accept multipart/mixed messages as a POST. The issue I am facing is how to mock up such a request in a unit test?

The core of the API method is:

public HttpResponseMessage Post(){
    var parsedContent=Request.Content.ReadAsMultipartAsync().Result;
    foreach(var item in parsedContent.Contents) {
        switch(item.Headers.ContentType.MediaType){
            case "application/json":
                doSomething(item);
                break;
            case "text/plain":
                doSomethingElse(item);
                break;
            case "application/pdf":
                doAnotherThing(item);
                break;
            case "image/png":
                doYetAnotherThing(item);
                break;
        }
    }
    //return status message based on results of previous calls...
}

I know that I have to create the request object and seed my test conditions into it, and the controller, before calling post in my test. What I am having trouble sorting out is the correct way to get the multipart content into the correct form for the ReadAsMultipartAsync() call.

I pieced this method together, and the request it creates is accepted and parsed correctly when fed into the above controller. However, setting a break point and inspecting the request object looks very different when built by this test vs. generated by something like fiddler and coming in through the pipeline. The pipeline has content of the type System.Web.Http.WebHost.HttpControllerHandler.LazyStreamContent while the test debug is System.Net.Http.MultipartContent.

public static HttpRequestMessage CreateMixedPostRequest(string url, IEnumerable<HttpContent> contentItems) {
    var request=new HttpRequestMessage(HttpMethod.Post, url);
    var content=new MultipartContent("mixed");
    foreach(var item in contentItems) {
        content.Add(item);
    }
    request.Content=content;
    return request;
}

I guess I am worried that this technique will lead to a false sense of security because the test is not feeding things to the controller in the same format as the pipeline will when this goes live. Is there a better way to build the requests for my tests? Or am I being overly paranoid, and this is a viable option for my scenario?

EDIT: We have reached the point where we are trying to test this endpoint from external code and we are seeing significant performance differences between the LazyStream and Multipart. The external code commonly gets timeouts when submitting the same data as the internal tests.

like image 310
Rozwel Avatar asked Nov 10 '15 00:11

Rozwel


1 Answers

The purpose of a unit test is to ensure that once you receive the data your code is behaving correctly. You can safely assume that the pipe will work correctly, assuming that you understand how the pipeline works. I would continue with your unit tests in the fashion that you've laid out, and then follow up with some live integration tests to ensure that the pipeline is working as expected. The integration tests can be run as part of a verification test suite that doesn't necessarily run with each build, since it is just confirmation of your assumptions about the functionality of the pipeline.

like image 182
Steve Mitcham Avatar answered Oct 14 '22 19:10

Steve Mitcham