Search code examples
unit-testingasp.net-web-apimockingmoqmediatypeformatter

Unable to mock Configuration.Formatters using Moq


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?


Solution

  • 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.