在 CosmosDB 中模拟 ItemResponse
Mocking ItemResponse in CosmosDB
我正在 xUnit 中使用 Moq 为涉及 CosmosDB 的服务编写单元测试。有一个方法 GetVehicleInfo
which returns ItemResponse<VehicleInfo>
来自 CosmosDB。由于 ItemResponse
有一个受保护的构造函数,所以我不能更新它。因此,我正在模拟调用方方法并执行
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);
我面临的问题是,当如下调用 GetVehicleInfo
时,它总是 returns null
。我希望它 return ItemResponse<VehicleInfo>
其中 Resource
将包含 expectedItem
.
ItemResponse<VehicleInfo> response = await _cosmosRepo.GetVehicleInfo(plate, country);
if (response == null){ //... }
您应该像这样设置您的 cosmoRepoServiceStub:
cosmoRepoServiceStub
.Setup(service => service.GetVehicleInfo(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(responseMock.Object);
GetVehicleInfo
参数应该是setup方法中的任意字符串
- 与其在方法选择器中调用
.Result
,不如使用 ReturnsAsync
或者如果您确实需要将 "a1"
作为第一个参数,则将其定义为
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);
更新#1反映到评论
Why does It.IsAny
work whereas "a1"
does not?
Moq uses 在幕后使用 object.Equals
来检查 Setup
的参数与实际调用的参数。
这意味着值类型和字符串的比较是基于它们的值(而不是基于它们的引用)。
因此,在您的特定情况下,这意味着 plate
或 country
分别不包含 a1
或 a2
字符串。
总之我应该工作,但根据一般经验
- 让您的
Setup
尽可能通用
- 让你的
Verify
尽可能具体
我正在 xUnit 中使用 Moq 为涉及 CosmosDB 的服务编写单元测试。有一个方法 GetVehicleInfo
which returns ItemResponse<VehicleInfo>
来自 CosmosDB。由于 ItemResponse
有一个受保护的构造函数,所以我不能更新它。因此,我正在模拟调用方方法并执行
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);
我面临的问题是,当如下调用 GetVehicleInfo
时,它总是 returns null
。我希望它 return ItemResponse<VehicleInfo>
其中 Resource
将包含 expectedItem
.
ItemResponse<VehicleInfo> response = await _cosmosRepo.GetVehicleInfo(plate, country);
if (response == null){ //... }
您应该像这样设置您的 cosmoRepoServiceStub:
cosmoRepoServiceStub
.Setup(service => service.GetVehicleInfo(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(responseMock.Object);
GetVehicleInfo
参数应该是setup方法中的任意字符串- 与其在方法选择器中调用
.Result
,不如使用ReturnsAsync
或者如果您确实需要将 "a1"
作为第一个参数,则将其定义为
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);
更新#1反映到评论
Why does
It.IsAny
work whereas"a1"
does not?
Moq uses 在幕后使用 object.Equals
来检查 Setup
的参数与实际调用的参数。
这意味着值类型和字符串的比较是基于它们的值(而不是基于它们的引用)。
因此,在您的特定情况下,这意味着 plate
或 country
分别不包含 a1
或 a2
字符串。
总之我应该工作,但根据一般经验
- 让您的
Setup
尽可能通用 - 让你的
Verify
尽可能具体