为何Mock中配置的Protected方法未返回预期值?
问题原因及解决方案
核心问题
你mock的是IMockTarget接口的MyProtectedGetIntMethod方法,但被测类ClassToTest的GetPrefixedValue方法里,调用的是自身类的MyProtectedGetIntMethod,而非传入的provider(mock对象)的同名方法。这就是为什么你设置的返回值1不生效,实际返回的是ClassToTest自身方法的99。
修复方案
根据测试预期,有两种常见修复方式:
方案1:调整接口方法访问级别(推荐)
把IMockTarget里的MyProtectedGetIntMethod改为public,这样可以直接调用传入对象的方法:
public interface IMockTarget { string PropertyToMock { get; } int MyProtectedGetIntMethod(); // 修改为public } public class ClassToTest { public string GetPrefixedValue(IMockTarget provider) { var x = provider.MyProtectedGetIntMethod(); // 调用provider的方法 return $"Prefixed:{provider.PropertyToMock}{x}"; } protected int MyProtectedGetIntMethod() { return 99; } }
测试代码无需修改,此时mock的返回值1会正常生效,测试可通过。
方案2:通过反射调用接口的protected方法
如果必须保持接口方法为protected,可以在ClassToTest里用反射调用传入对象的方法:
public class ClassToTest { public string GetPrefixedValue(IMockTarget provider) { // 反射调用IMockTarget的protected方法 var method = typeof(IMockTarget).GetMethod("MyProtectedGetIntMethod", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); var x = (int)method.Invoke(provider, null); return $"Prefixed:{provider.PropertyToMock}{x}"; } protected int MyProtectedGetIntMethod() { return 99; } }
测试代码保持不变,同样能正确调用到mock的方法并返回1。
额外场景:mock被测类自身的保护方法
如果你的测试意图是替换ClassToTest自身的MyProtectedGetIntMethod返回值,那应该mockClassToTest类而非IMockTarget接口,示例代码如下:
[TestMethod] public void TestMethod2() { // mock ClassToTest类,CallBase确保其他方法正常执行 var mockSut = new Mock<ClassToTest> { CallBase = true }; mockSut.Protected() .Setup<int>("MyProtectedGetIntMethod") .Returns(1); var mockTarget = new Mock<IMockTarget>(); mockTarget.SetupGet(x => x.PropertyToMock).Returns("FixedValue"); var actualValue = mockSut.Object.GetPrefixedValue(mockTarget.Object); Assert.AreEqual("Prefixed:FixedValue1", actualValue); }
内容的提问来源于stack exchange,提问作者Rod
相关产品推荐
相关产品推荐

