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);
GetVehicleInfoparameters should any string in the setup method- Instead of calling the
.Resultinside 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.IsAnywork 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
Setupas generic as possible - Make your
Verifyas specific as possible
