I am writing unit tests for the existing Web API 2 project. For which i am using Ploeh Autofixture
and Moq
.
Test Method : UPDATED
[Test]
public async Task Service1_TestMethod() {
//some code here
var fakeemail = FakeBuilder.Create<string>("[email protected]");
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 Method :
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.
}
If i comment the Service2.AddUser
call then everything works. There is a lot of code in that method apart from this call. I am having problem with only this call. If this call returns the mocked HttpResponseMessage
then everything works.
Service2
is an external API. I am just wondering how to mock
HttpResponseMessage
. Any help is appreciated.
The stub you create with:
service2.Setup(i => i.AddUser(fakeUserInvite, fakeUserToken))
.ReturnsAsync(fakeHttpResponseMessage);
requires the actual call to be made with the exact same objects as the ones referenced by fakeUserInvite
and fakeUserToken
in order for Moq to return fakeHttpResponseMessage
.
This is because Moq's argument matching verifies that the arguments specified in the stub are equal to the ones made in the actual call. If they are not, the stub won't match and Moq will return the default value for the method's return type – in this case null
since HttpResponseMessage
is a reference type.
To solve this problem, you can either make sure that the fakeUserInvite
and fakeUserToken
references are being passed to the actual service2.AddUser
call or you can use somewhat less specific argument constraints.
Here's an example:
service2.Setup(i => i.AddUser(
It.Is<UserInvite>(u => u.EmailAddress == fakeEmail &&
u.Username == fakeEmail),
fakeUserToken))
.ReturnsAsync(fakeHttpResponseMessage);
Here we're stating that the AddUser
method should be called with:
UserInvite
object whose EmailAddress
and Username
properties have the same value as fakeEmail
as the first argumentfakeUserToken
as the second argumentIf the actual values of those arguments don't matter to your specific test scenario, you can tell Moq to always return fakeHttpResponseMessage
regardless of what arguments AddUser
is being called with by saying:
service2.Setup(i => i.AddUser(
It.IsAny<UserInvite>(),
It.IsAny<string>()))
.ReturnsAsync(fakeHttpResponseMessage);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With