1
votes

I am developing an ASP.NET web API application. I am unit testing to every component in my application. I am using Moq Unit Test framework to mock the data. Now I am trying to mock the Configuration.Formatters.JsonFormatter in my Unit test because my action under unit test is using it as follows:

public HttpResponseMessage Register(model)
{
    return new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.BadRequest,
                Content = new ObjectContent<List<string>>(errors, Configuration.Formatters.JsonFormatter)
            };
}

I am trying to mock the Configuration.Formatters.JsonFormatter in the Unit Test as follow.

[TestMethod]
public void Register_ReturnErrorsWithBadRequest_IfValidationFails()
{
    PostUserRegistration model = new PostUserRegistration {
        Name = "Wai Yan Hein",
        Email = "[email protected]",
        Password = ""
    };

    Mock<JsonMediaTypeFormatter> formatterMock = new Mock<JsonMediaTypeFormatter>();
    Mock<MediaTypeFormatterCollection> formatterCollection = new Mock<MediaTypeFormatterCollection>();
    formatterCollection.Setup(x => x.JsonFormatter).Returns(formatterMock.Object);
    Mock<HttpConfiguration> httpConfigMock = new Mock<HttpConfiguration>();
    httpConfigMock.Setup(x => x.Formatters).Returns(formatterCollection.Object);
    Mock<IAccountRepo> accRepoMock = new Mock<IAccountRepo>();

    AccountsController controller = new AccountsController(accRepoMock.Object);

    controller.Configuration = httpConfigMock.Object;
    controller.ModelState.AddModelError("", "Faking some model error");
    HttpResponseMessage response = controller.Register(model);
    Assert.AreEqual(response.StatusCode, System.Net.HttpStatusCode.BadRequest);
}

When I run my unit tests, it is giving me this error. enter image description here

System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: x => x.JsonFormatter

So, how can I fix that error and how can I mock Configuration.Formatters.JsonFormatter?

1
Everything would be much easier if you return Request.CreateResponse(HttpStatusCode.BadRequest, errors) from the action. In this case you don't even need to mock JsonFormatter. Another problem with your code is that you couple your API to JSON format. What about XML or other possible formats? - CodeFuller
Ok. I’ll try to use this way. - Wai Yan Hein

1 Answers

1
votes

You should not have to test that the framework is doing what it was designed to do. Instead, similar to what was suggested before in comments, I suggest using the built in methods of the ApiController and also refactoring the action to the syntax suggested from documentation for that version of Asp.Net Web API

public IHttpActionResult Register(PostUserRegistration model) {
    if (!ModelState.IsValid)
        return BadRequest(ModelState); //<-- will extract errors from model state

    //...code removed for brevity

    return Ok();
}

A simple example of a unit test for the above method could look something like this...

[TestMethod]
public void Register_ReturnErrorsWithBadRequest_IfValidationFails() {            
    //Arrange
    PostUserRegistration model = new PostUserRegistration {
        Name = "Wai Yan Hein",
        Email = "[email protected]",
        Password = ""
    };

    var accRepoMock = new Mock<IAccountRepo>();
    var controller = new AccountsController(accRepoMock.Object);
    controller.ModelState.AddModelError("", "Faking some model error");

    //Act
    var response = controller.Register(model) as InvalidModelStateResult; //<-- Note the cast here

    //Assert
    Assert.IsNotNull(response);
}

If the injected dependency is not going to be referenced/invoked in the method under test you could also forego the mock and inject null. That however is dependent on code not provided in the original question.