单元测试中如何验证函数调用参数的指定属性值?
解决单元测试中验证
ReplaceAsync参数的问题 你完全可以通过Moq的特性来捕获或者验证传递给ReplaceAsync的参数,这里有两种常用的方案:
方案一:用Callback捕获参数后断言
你之前觉得没法用回调其实是误解啦——回调不需要依赖方法的返回值,它只是在方法被调用时触发,帮你拿到传递的参数。具体步骤如下:
在测试类里声明一个变量用来存储捕获到的
JObject:private JObject _capturedDocument;在模拟
dbProvider的时候,添加Callback来捕获第二个参数:dbProvider.Setup(p => p.ReplaceAsync(It.IsAny<string>(), It.IsAny<JObject>())) .Callback<string, JObject>((user, document) => _capturedDocument = document) .Returns(Task.CompletedTask);调用
CustomerUpdate方法,然后对捕获到的参数做断言:// 调用待测试方法 await customerService.CustomerUpdate("testUser", originalJObject); // 验证属性值 Assert.AreEqual("foo", _capturedDocument["someFlag"].Value<string>()); Assert.IsNotNull(_capturedDocument["lastUpdate"].Value<DateTime>()); // 其他属性的验证逻辑
方案二:在Setup时直接验证参数匹配
如果你不想额外存储变量,也可以在Setup阶段就通过It.Is<T>来定义参数的匹配条件,后续通过Verify来确认方法被正确调用:
dbProvider.Setup(p => p.ReplaceAsync( It.IsAny<string>(), It.Is<JObject>(doc => doc["someFlag"].Value<string>() == "foo" && doc["lastUpdate"] != null && // 可以添加更多属性的验证条件 doc["otherProperty"].Value<int>() == 123 ))) .Returns(Task.CompletedTask); // 调用待测试方法 await customerService.CustomerUpdate("testUser", originalJObject); // 验证方法确实被调用了(如果参数不匹配,这里会失败) dbProvider.Verify(p => p.ReplaceAsync(It.IsAny<string>(), It.IsAny<JObject>()), Times.Once);
这种方式的好处是,只要参数不符合你定义的条件,Setup就不会匹配,Verify时就会抛出异常,直接提示参数不满足预期。
注意事项
- 访问
JObject的属性时,建议用Value<T>()方法来做类型转换,避免直接ToString可能带来的空引用问题。 - 如果你的
CustomerUpdate是异步方法,测试方法一定要标记为async并使用await调用,否则测试会提前结束,导致断言失效。
内容的提问来源于stack exchange,提问作者90abyss
相关产品推荐
相关产品推荐

