能否将Mock对象的调用次数作为参数传入单元测试类方法?
问题解决:单元测试方法扩展为接收Mock预期调用次数参数
编译失败的核心原因是:[InlineData]要求传入的参数必须是编译时常量,而Times.Never、Times.Once是Times结构体的运行时实例,不属于编译时常量范畴,因此无法直接用于InlineData。
以下两种方案可以实现你的需求:
方案1:使用MemberData提供测试数据
MemberData支持返回任意类型的测试数据,完美适配Times类型的传递需求:
public class YourTestClass { // 定义静态测试数据源 public static IEnumerable<object[]> VerificationTestData() { yield return new object[] { "", Times.Never }; yield return new object[] { "test", Times.Once }; } [Theory] [MemberData(nameof(VerificationTestData))] public async Task PostAsync_SendAsync_VerifyOnce(string id, Times outcome) { var mockClients = new Mock<IHubClients>(); // ... 你的业务逻辑与Mock配置代码 ... mockClients.Verify(clients => clients.Client(id), outcome); } }
注意:将async void改为async Task是单元测试的最佳实践——async void会导致测试框架无法正确等待异步操作完成,可能出现测试结果不准确的问题。
方案2:通过枚举/整数映射转换为Times
如果更倾向于使用InlineData的简洁性,可以先传入简单的常量类型,再在测试方法内转换为Times实例:
枚举映射方式
// 定义预期调用次数枚举 public enum ExpectedCallFrequency { Never, Once } [Theory] [InlineData("", ExpectedCallFrequency.Never)] [InlineData("test", ExpectedCallFrequency.Once)] public async Task PostAsync_SendAsync_VerifyOnce(string id, ExpectedCallFrequency frequency) { var mockClients = new Mock<IHubClients>(); // ... 你的业务逻辑与Mock配置代码 ... // 将枚举转换为Times实例 Times outcome = frequency switch { ExpectedCallFrequency.Never => Times.Never, ExpectedCallFrequency.Once => Times.Once, _ => throw new ArgumentOutOfRangeException(nameof(frequency)) }; mockClients.Verify(clients => clients.Client(id), outcome); }
整数映射方式
[Theory] [InlineData("", 0)] [InlineData("test", 1)] public async Task PostAsync_SendAsync_VerifyOnce(string id, int expectedCallCount) { var mockClients = new Mock<IHubClients>(); // ... 你的业务逻辑与Mock配置代码 ... Times outcome = expectedCallCount == 0 ? Times.Never : Times.Exactly(expectedCallCount); mockClients.Verify(clients => clients.Client(id), outcome); }
两种方案都能实现你的测试需求:空id时验证调用从未发生,有效id时验证调用发生一次。
内容的提问来源于stack exchange,提问作者Pradeep Patel
相关产品推荐
相关产品推荐

