【问题标题】:Unable to mock Configuration.Formatters using Moq无法使用 Moq 模拟 Configuration.Formatters
【发布时间】:2018-08-27 06:45:40
【问题描述】:

我正在开发一个 ASP.NET Web API 应用程序。我正在对我的应用程序中的每个组件进行单元测试。我正在使用 Moq 单元测试框架来模拟数据。现在我试图在我的单元测试中模拟Configuration.Formatters.JsonFormatter,因为我在单元测试下的操作如下使用它:

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

我正在尝试在单元测试中模拟Configuration.Formatters.JsonFormatter,如下所示。

[TestMethod]
public void Register_ReturnErrorsWithBadRequest_IfValidationFails()
{
    PostUserRegistration model = new PostUserRegistration {
        Name = "Wai Yan Hein",
        Email = "waiyanhein@gmail.com",
        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);
}

当我运行单元测试时,它给了我这个错误。

System.NotSupportedException:非虚拟机上的设置无效 (在 VB 中可重写)成员:x => x.JsonFormatter

那么,我该如何修复该错误以及如何模拟 Configuration.Formatters.JsonFormatter

【问题讨论】:

  • 如果您从操作中返回 Request.CreateResponse(HttpStatusCode.BadRequest, errors),一切都会容易得多。在这种情况下,您甚至不需要模拟 JsonFormatter。您的代码的另一个问题是您将 API 耦合到 JSON 格式。 XML 或其他可能的格式呢?
  • 好的。我会尝试使用这种方式。

标签: unit-testing asp.net-web-api mocking moq mediatypeformatter


【解决方案1】:

您不应该测试框架是否正在执行其设计的任务。相反,类似于之前在 cmets 中的建议,我建议使用 ApiController 的内置方法,并将操作重构为该版本 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();
}

上述方法的单元测试的简单示例可能如下所示...

[TestMethod]
public void Register_ReturnErrorsWithBadRequest_IfValidationFails() {            
    //Arrange
    PostUserRegistration model = new PostUserRegistration {
        Name = "Wai Yan Hein",
        Email = "waiyanhein@gmail.com",
        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);
}

如果在被测方法中不会引用/调用注入的依赖项,您也可以放弃模拟并注入null。但是,这取决于原始问题中未提供的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-12
    • 2011-01-18
    • 2011-06-13
    • 2019-09-11
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多