如何捕获C#中Mock对象方法的返回值并验证?
我有如下C#方法:
public class MyClass { public bool foo(Dependency dependency) { bool result = false; var metadata = dependency.dependencyMethod(); if(metadata.containsProperty()){ // doSomething } else { // doSomethingElse } return result; } }
我希望捕获dependency.dependencyMethod()的返回值(即方法中metadata变量的值),并断言该返回值与我为Mock对象定义的预设响应值一致。我的测试代码如下:
//Arrange MyClass myClass = new MyClass(); // System Under Test Mock<Dependency> dependencyMock = new Mock<Dependency>(); //Mocking dependency // Mocking the behavior of the dependencyMock to return a pre-defined value when invoked dependencyMock .Setup(d => d.dependencyMethod()) .Returns("dummyMetadata"); // How do we capture the value returned when `dependencyMock.dependencyMethod()` gets invoked? dependencyMock .Setup(d => d.dependencyMethod()) // When invoking the `dependencyMethod()` .Callback(); // <--- How to Capture the value returned when d.dependencyMethod() gets called, and assert that it matches "dummyMetaData"? // Act myClass.foo(dependencyMock);
我能否捕获dependencyMock.dependencyMethod()的返回值?即使该返回值是Mock的,我也希望捕获它并确认预设的Mock响应确实被返回。
首先明确:你其实不需要刻意捕获Mock方法的返回值来断言它和预设值一致——因为你已经通过Returns("dummyMetadata")强制Mock返回这个值了,只要方法被正确调用,返回值必然是你预设的内容。
不过如果你一定要验证这个逻辑,或者想确认被测试类(SUT)确实拿到了这个返回值,可以用以下几种方式:
方式1:验证Mock方法的调用次数(最直接)
既然已经预设了返回值,只要验证dependencyMethod被调用过,就说明foo方法确实拿到了你预设的返回值。在Act步骤后添加断言:
// Assert dependencyMock.Verify(d => d.dependencyMethod(), Times.Once);
这能确保foo方法正确调用了依赖的dependencyMethod,结合之前的Setup配置,就等同于确认SUT拿到了预设的dummyMetadata。
方式2:用Callback捕获返回值(如果一定要拿到具体值)
如果你确实需要捕获返回值,可以在Setup时把预设值存到变量里,再通过Callback赋值并断言:
// Arrange string expectedMetadata = "dummyMetadata"; MyClass myClass = new MyClass(); Mock<Dependency> dependencyMock = new Mock<Dependency>(); string capturedMetadata = null; dependencyMock .Setup(d => d.dependencyMethod()) .Returns(expectedMetadata) .Callback(() => { capturedMetadata = expectedMetadata; }); // Act myClass.foo(dependencyMock.Object); // 注意:必须传mock的Object属性,而非Mock容器本身! // Assert Assert.AreEqual(expectedMetadata, capturedMetadata);
重要修正:你的测试代码里存在一个错误——调用myClass.foo(dependencyMock)是不正确的,应该传递dependencyMock.Object,因为Mock<T>是Mock的管理容器,真正的依赖实例是它的Object属性。
方式3:验证预设逻辑的有效性
如果你担心预设的返回值没生效,其实完全没必要——Moq的Setup是强绑定的,只要方法调用的匹配条件符合,就一定会返回你设置的值。验证调用次数已经足够确认逻辑的正确性。
内容的提问来源于stack exchange,提问作者Vismark Juarez

