I am writing unit tests using Moq in xUnit for a service that involves CosmosDB. There's a method GetVehicleInfo
which returns ItemResponse<VehicleInfo>
from CosmosDB. As ItemResponse
has a protected constructor so I can't new it up. Therefore, I'm mocking the caller method and doing
var responseMock = new Mock<ItemResponse<VehicleInfo>>();
responseMock.Setup(x => x.Resource).Returns(expectedItem); //expectedItem is of VehicleInfo type
cosmoRepoServiceStub.Setup(service => service.GetVehicleInfo("a1", "a2").Result).Returns(responseMock.Object);
The problem I face is that when GetVehicleInfo
is called as below, it returns null
always. I expect it to return ItemResponse<VehicleInfo>
wherein Resource
will contain expectedItem
.
ItemResponse<VehicleInfo> response = await _cosmosRepo.GetVehicleInfo(plate, country);
if (response == null){ //... }
CodePudding user response:
You should setup your cosmoRepoServiceStub like this:
cosmoRepoServiceStub
.Setup(service => service.GetVehicleInfo(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(responseMock.Object);
GetVehicleInfo
parameters should any string in the setup method- Instead of calling the
.Result
inside the method selector please preferReturnsAsync
Or if you really need to anticipate "a1"
as a first argument then define it as
const StringComparison comparison = StringComparison.OrdinalIgnoreCase;
cosmoRepoServiceStub
.Setup(service => service.GetVehicleInfo(
It.Is<string>(param1 => string.Equals(param1, "a1", comparison),
It.Is<string>(param1 => string.Equals(param1, "a2", comparison)))
.ReturnsAsync(responseMock.Object);
UPDATE #1 Reflect to comment
Why does
It.IsAny
work whereas"a1"
does not?
Moq uses uses object.Equals
under the hood to check the Setup
's argument against the actual invocation's argument.
This means that the comparison for value types and for strings are based on their values (not based on their references).
So, in your particular case that means either plate
or country
does not contain a1
or a2
strings respectively.
In short I should work, but as a general rule of thumb
- Make your
Setup
as generic as possible - Make your
Verify
as specific as possible