【问题标题】:Mock HttpResponseMessage while unit testing API with Moq and AutoFixture在使用 Moq 和 AutoFixture 对 API 进行单元测试时模拟 HttpResponseMessage
【发布时间】:2016-12-25 05:40:47
【问题描述】:

我正在为现有的 Web API 2 项目编写单元测试。我正在为此使用Ploeh AutofixtureMoq

测试方法: 更新

 [Test]
    public async Task Service1_TestMethod() {

      //some code here
     var fakeemail = FakeBuilder.Create<string>("test1234@test.com");
      var fakeUserInvite =
                FakeBuilder.Build<UserInvite>()
                    .With(i => i.EmailAddress, fakeemail)
                    .With(i => i.Username, fakeemail)
                    .Create();
      var fakeUserToken = FakeBuilder.Create<string>();
      var fakeHttpResponseMessage =
                    Fixture.Build<HttpResponseMessage>()
                                 .With(h => h.StatusCode, HttpStatusCode.OK).Create();
  //Here i am mocking another service method. Whose response is HttpResponseMessage.
  Service2.Setup(i => i.AddUser(fakeUserInvite, fakeUserToken))
            .ReturnsAsync(fakeHttpResponseMessage);

  var result = await Service1.AddUser( /*   */);

}

Service1 方法:

   public async Task<bool> AddUser(/*   */)
   {
    var response = await Service2.AddUser(userInvite, userToken); // response is null even after mocking it.

   // Add user code follows bassed on the above response.  

   }

如果我评论Service2.AddUser 电话,那么一切正常。除了这个调用之外,该方法中有很多代码。我只有这个电话有问题。如果此调用返回模拟的HttpResponseMessage,那么一切正常。

Service2 是一个外部 API。我只是想知道如何mockHttpResponseMessage。任何帮助表示赞赏。

【问题讨论】:

  • 你有什么异常吗?如果是,是哪一个?
  • 没有例外。对于调用Service2.AddUser,只有response 为空。我希望response 成为我在setup 调用时嘲笑的对象fakeHttpResponseMessage
  • 如何将fakeUserInvitefakeUserToken 传递给Service2.AddUser 方法?实际调用需要使用这些相同的对象,以便 Moq 返回您的 fakeHttpResponseMessage。请参阅 Moq 文档中的 matching arguments
  • Service2.AddUser 是静态方法吗?如果没有,Service2 测试替身如何传递给Service1
  • 请证明minimal reproducible example,以便其他人可以重现和理解问题以提供更好的帮助。

标签: c# unit-testing asp.net-web-api2 moq autofixture


【解决方案1】:

您创建的存根:

service2.Setup(i => i.AddUser(fakeUserInvite, fakeUserToken))
        .ReturnsAsync(fakeHttpResponseMessage);

需要使用与fakeUserInvitefakeUserToken 引用的对象完全相同的相同 对象进行实际调用,以便Moq 返回fakeHttpResponseMessage

这是因为Moq's argument matching 验证存根中指定的参数与实际调用中的参数相等。如果不匹配,则存根将不匹配,并且 Moq 将返回方法返回类型的默认值——在本例中为 null,因为 HttpResponseMessage 是一个引用类型。

要解决此问题,您可以确保将fakeUserInvitefakeUserToken 引用传递给实际的service2.AddUser 调用,或者您可以使用不太具体的argument constraints

这是一个例子:

service2.Setup(i => i.AddUser(
            It.Is<UserInvite>(u => u.EmailAddress == fakeEmail &&
                                   u.Username == fakeEmail),
            fakeUserToken))
        .ReturnsAsync(fakeHttpResponseMessage);

这里我们声明AddUser 方法应该被调用:

  1. 一个UserInvite 对象,其EmailAddressUsername 属性与fakeEmail 作为第一个参数具有相同的值
  2. fakeUserToken 相同的值作为第二个参数

如果这些参数的实际值对您的特定测试场景无关紧要,您可以告诉 Moq 总是返回 fakeHttpResponseMessage 而不管 AddUser 被调用的参数是什么:

service2.Setup(i => i.AddUser(
            It.IsAny<UserInvite>(),
            It.IsAny<string>()))
        .ReturnsAsync(fakeHttpResponseMessage);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 2023-03-29
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多