混合使用来自同一类的已实现方法和模拟方法

时间:2020-08-18 15:49:32

标签: c# moq

我正在尝试模拟类的某些方法,同时保留其他方法的真实实现。

现在,我确实发现了与stackoverflow here相关的内容。但是,没有建议的答案对我有帮助。

李的答案在大多数情况下可能是好的,但是在我的情况下这是不合适的,因为我真的需要模拟接口(具有各种实现)而不是类本身。

布兰登的答案非常接近,但我发现了以下建议。
这是为方便起见粘贴的他的代码:

var mock = new Mock<ITestClass>(); // Create Mock of interface

// Create instance of ITestClass implementation you want to use
var inst = new ActualTestClass();

// Setup to call method of an actual instance
// if method returns void use mock.Setup(...).Callback(...)
mock.Setup(m => m.SomeMethod(It.IsAny<int>())
    .Returns((int x) => inst.SomeMethod(x));

引起我问题的是,该示例适用于简单的场景,但是如果“ SomeMethod()”调用它从具有模拟设置的ITestClass中调用另一个方法,则该示例将不起作用。在这种情况下,“ SomeMethod()”仍将使用实际实现。

为清楚起见:
说ITestClass实现方法SomeMethod和SomeOtherMethod。前者必须调用按以下方式嘲笑的后者:

mock.Setup(m => m.SomeOtherMethod(It.IsAny<bool>())
     .Returns(true);

现在该模拟方法如何由SomeMethod代替真正的实现使用?

编辑

我需要模拟一个接口而不是类本身的另一个原因是,如果它是单例,则后一个选项将不允许您测试TestClass()。

2 个答案:

答案 0 :(得分:1)

流行的隔离框架(例如Moq,NSubstitute或FakeItEasy)受到约束。不可能用它们解决您的问题。

还有不受约束的隔离框架:TypeMock,JustMock(均为付费)和MS Fakes(仅在VS Enterprise中可用)。

但是,我最近遇到了一个有趣的免费Pose库,它将解决您的问题。

添加package

打开名称空间:

using Pose;

测试代码:

var inst = new ActualTestClass();

Shim testClassShim = Shim.Replace(() => inst.SomeOtherMethod(Is.A<bool>()))
    .With((ActualTestClass _, bool b) => true);

int actual = 0;

PoseContext.Isolate(() =>
{
    actual = inst.SomeMethod(1); // it will use shim inside
},
testClassShim);

Assert.Equal(0, actual);

但是它在许多方面仍然不如商业同行。

应该注意的是,不受约束的工具虽然可以非常有效地解决隔离问题,但是以这种方式,它们可以避免设计错误,最终可能导致不良的应用程序体系结构。

答案 1 :(得分:1)

完全不用Moq怎么办?
您可以创建一个包装类,该包装类从您的主类派生,并使用所需的内容覆盖要模拟的方法。
然后在测试中使用此派生类。
当然,这些重写的方法可以使用Moq或从该派生类中定义为模拟。

相关问题