jeudi 20 septembre 2018

Testing model with a property that has a default value doesn't work

I have an API that I am writing some consumer based tests for. In this API I send a request out to the endpoint with a JSON payload. When I try to create tests against my code and I hit the Post endpoint I get null for properties that I've set to a default value (like Country, and SpecialCodes below).

However, whenever I run this code locally it works fine and when I hit my Post everything is set to the default values I would expect.

When I am testing if I remove the [FromBody] attribute from the method signature then the default values are what I would expect, but obviously nothing in my body gets deserialized properly anymore.

Is there something extra needed for tests to get these default values to populate?

I know that my request I'm sending is correct because if I simply provide a Country and a SpecialCodes code then all is well and those properties are deserialized to whatever I provide them. Obviously my workaround to all of this is to just provide these values in my test and everything works, but it's nagging at the core of me as to why it doesn't work without those values...

The endpoint is setup like this:

[HttpPost("MyEndpoint")]
public async Task<IActionResult> Post([FromBody] ExampleModel model)
{
    //Downstream in this method I manipulate `Country` and `SpecialCodes`
    //In prod or when running locally those are set to the default value if I have not 
    //provided them in the request. When testing they come in as null
    //causing this method to throw an exception and return a 500...
}

My ExampleModel is setup like this:

public class ExampleModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string Country { get; set; } = "US"
    public SpecialCodes SpecialCodes { get; set; } = new SpecialCodes();
}

Finally my SpecialCodes class is setup like this:

public class SpecialCodes
{
    public string SuperSecretCode { get; set; } = "Abc";
    public string NotSoSecretCode { get; set; } = "Cba";
}

Here is how the test is setup:

[TestMethod]
public async Task MySuperSecretTest_WhenIsSuccessful_ReturnsValidData()
{
    var request = BuildRequest();

    // Send request
    var response = await MyEndpointRequestAsync(request);

    // It never makes it here because it blows up in the method above...
    var responseObject = JsonConvert.DeserializeObject<MyResponseDto>(response);

    // Validate
    Assert.IsNotNull(response);
    Assert.IsNotNull(responseObject);

}

Then MyEndpointRequestAsync is setup like so:

public static async Task<string> MyEndpointRequestAsync(MyExampleData request)
{
    var content = JsonConvert.SerializeObject(request);
    var postRequest = new HttpRequestMessage(HttpMethod.Post, $"/MyEndpoint");
    var buffer = System.Text.Encoding.UTF8.GetBytes(content);
    using (var byteContent = new ByteArrayContent(buffer))
    {
        byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        postRequest.Content = byteContent;
        var response = await Test.Client.SendAsync(postRequest);

        //I get a 500 back, blows up...
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
    }
}

Aucun commentaire:

Enregistrer un commentaire