使用Moq验证方法调用及返回结果(IsSuccessful为true)
统一验证泛型PerformAction的调用及返回结果
现有代码定义
class ClassA<T> { T DoSomething(); } class ResultWrapper<T> { bool IsSuccessful; T Data; } class PerformAction<T> { ResultWrapper<T> DoSomething() { try { var classA = new ClassA<T>(); var result = new ResultWrapper<T>(); result.Data = classA.DoSomething(); result.IsSuccessful=true; return result; } catch(Exception) { var result = new ResultWrapper<T>(); result.IsSuccessful=false; return result; } } }
现有验证方式的局限
常规Moq验证只能检查PerformAction<T>的DoSomething方法是否被调用:
Mock<PerformAction<ABC>> mockObject = new Mock<PerformAction<ABC>>(); mockObject.Verify(x => x.DoSomething(), Times.Once());
但这种方式无法同时验证返回的ResultWrapper<T>.IsSuccessful是否为true。如果存在大量不同泛型参数的PerformAction实现(如PerformAction<BCD>、PerformAction<CDF>等),且mock在100处测试中被使用,每个测试都重复编写返回值断言会非常繁琐。
解决方案:创建通用验证扩展方法
通过扩展Moq的Mock类,实现一个通用的验证方法,一次性完成方法调用次数验证和返回结果断言:
扩展方法代码
using Moq; using Xunit; // 替换为你使用的测试框架Assert类 public static class MockExtensions { public static void VerifyDoSuccessfulAction<T>(this Mock<PerformAction<T>> mock, Times times) { // 验证方法调用次数 mock.Verify(x => x.DoSomething(), times); // 获取返回值并验证IsSuccessful为true var result = mock.Object.DoSomething(); Assert.True(result.IsSuccessful); } }
使用方式
在任何测试中只需调用该扩展方法,无需重复编写断言:
Mock<PerformAction<ABC>> mock = new Mock<PerformAction<ABC>>(); // 预先模拟成功返回(如果需要) mock.Setup(x => x.DoSomething()).Returns(new ResultWrapper<ABC> { IsSuccessful = true }); // 执行测试逻辑... // 一次性完成两项验证 mock.VerifyDoSuccessfulAction(Times.Once());
进阶:自动生成成功mock
如果希望所有PerformAction<T>的mock默认返回成功结果,可以创建通用的mock创建方法,进一步减少重复代码:
public static Mock<PerformAction<T>> CreateSuccessfulPerformActionMock<T>() { var mock = new Mock<PerformAction<T>>(); mock.Setup(x => x.DoSomething()).Returns(new ResultWrapper<T> { IsSuccessful = true }); return mock; }
使用时直接创建mock即可:
var mock = CreateSuccessfulPerformActionMock<ABC>(); // 执行测试... mock.VerifyDoSuccessfulAction(Times.Once());
替代方案:用Callback捕获返回值
如果不想编写扩展方法,也可以通过Callback捕获返回值后断言,但这种方式仍需每个测试重复编写:
ResultWrapper<ABC> result = null; Mock<PerformAction<ABC>> mock = new Mock<PerformAction<ABC>>(); mock.Setup(x => x.DoSomething()).Returns(new ResultWrapper<ABC> { IsSuccessful = true }) .Callback(() => result = mock.Object.DoSomething()); // 执行测试... mock.Verify(x => x.DoSomething(), Times.Once()); Assert.True(result.IsSuccessful);
内容的提问来源于stack exchange,提问作者Hiren Desai
相关产品推荐
相关产品推荐

