使用 Moq 和 AutoFixture 进行单元测试时模拟 HttpResponseMessage API
Mock HttpResponseMessage while unit testing API with Moq and AutoFixture
我正在为现有的 Web API 2 项目编写单元测试。为此我使用 Ploeh Autofixture
和 Moq
.
测试方法:
已更新
[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( /* */);
}
服务 1 方法:
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
调用,那么一切正常。除了这个调用之外,该方法中还有很多代码。我只有这个电话有问题。如果这个调用 returns 模拟的 HttpResponseMessage
那么一切正常。
Service2
是一个外部 API。我只是想知道如何 mock
HttpResponseMessage
。感谢您的帮助。
您创建的存根:
service2.Setup(i => i.AddUser(fakeUserInvite, fakeUserToken))
.ReturnsAsync(fakeHttpResponseMessage);
要求使用与 fakeUserInvite
和 fakeUserToken
引用的对象完全 相同的 对象进行实际调用,以便 Moq return fakeHttpResponseMessage
.
这是因为 Moq's argument matching 验证存根中指定的参数 等于 实际调用中的参数。如果它们不匹配,存根将不匹配,Moq 将 return 方法的 return 类型的默认值——在本例中为 null
因为 HttpResponseMessage
是引用类型.
要解决此问题,您可以确保将 fakeUserInvite
和 fakeUserToken
引用传递给实际的 service2.AddUser
调用,或者您可以使用不太具体的 argument constraints.
这是一个例子:
service2.Setup(i => i.AddUser(
It.Is<UserInvite>(u => u.EmailAddress == fakeEmail &&
u.Username == fakeEmail),
fakeUserToken))
.ReturnsAsync(fakeHttpResponseMessage);
这里我们声明 AddUser
方法应该被调用:
- 一个
UserInvite
对象,其 EmailAddress
和 Username
属性与第一个参数 fakeEmail
的值相同
- 与第二个参数
fakeUserToken
相同的值
如果这些参数的实际值对您的特定测试场景无关紧要,您可以告诉 Moq always return fakeHttpResponseMessage
无论通过说:
调用什么参数 AddUser
service2.Setup(i => i.AddUser(
It.IsAny<UserInvite>(),
It.IsAny<string>()))
.ReturnsAsync(fakeHttpResponseMessage);
我正在为现有的 Web API 2 项目编写单元测试。为此我使用 Ploeh Autofixture
和 Moq
.
测试方法: 已更新
[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( /* */);
}
服务 1 方法:
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
调用,那么一切正常。除了这个调用之外,该方法中还有很多代码。我只有这个电话有问题。如果这个调用 returns 模拟的 HttpResponseMessage
那么一切正常。
Service2
是一个外部 API。我只是想知道如何 mock
HttpResponseMessage
。感谢您的帮助。
您创建的存根:
service2.Setup(i => i.AddUser(fakeUserInvite, fakeUserToken))
.ReturnsAsync(fakeHttpResponseMessage);
要求使用与 fakeUserInvite
和 fakeUserToken
引用的对象完全 相同的 对象进行实际调用,以便 Moq return fakeHttpResponseMessage
.
这是因为 Moq's argument matching 验证存根中指定的参数 等于 实际调用中的参数。如果它们不匹配,存根将不匹配,Moq 将 return 方法的 return 类型的默认值——在本例中为 null
因为 HttpResponseMessage
是引用类型.
要解决此问题,您可以确保将 fakeUserInvite
和 fakeUserToken
引用传递给实际的 service2.AddUser
调用,或者您可以使用不太具体的 argument constraints.
这是一个例子:
service2.Setup(i => i.AddUser(
It.Is<UserInvite>(u => u.EmailAddress == fakeEmail &&
u.Username == fakeEmail),
fakeUserToken))
.ReturnsAsync(fakeHttpResponseMessage);
这里我们声明 AddUser
方法应该被调用:
- 一个
UserInvite
对象,其EmailAddress
和Username
属性与第一个参数fakeEmail
的值相同 - 与第二个参数
fakeUserToken
相同的值
如果这些参数的实际值对您的特定测试场景无关紧要,您可以告诉 Moq always return fakeHttpResponseMessage
无论通过说:
AddUser
service2.Setup(i => i.AddUser(
It.IsAny<UserInvite>(),
It.IsAny<string>()))
.ReturnsAsync(fakeHttpResponseMessage);