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



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

现在,我确实在这里发现了一些与stackoverflow有关的东西。然而,没有一个建议的答案对我有帮助。

Lee的回答在大多数情况下可能是好的,但在我的情况下是不合适的,因为我真的需要模拟一个接口(它有各种实现(,而不是类本身。

布兰登的回答很接近,但我发现了以下问题
这是为了方便粘贴的他的代码:

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中调用另一个具有mock设置的方法。在这种情况下;SomeMethod(("仍将使用真正的实现。

为了清楚起见:
Say ITestClass实现了SomeMethod和SomeOtherMethod方法。前者必须调用后者,后者被嘲笑为:

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

现在SomeMethod如何使用这个mock而不是真正的实现呢?

编辑

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

Moq、NSubstitute或FakeItEasy等流行的隔离框架受到约束。不可能和他们一起解决你的问题。

还有不受约束的隔离框架:TypeMock、JustLock(两者都是付费的(和MS Fakes(仅在VS Enterprise中可用(。

然而,我最近遇到了一个有趣的免费Pose库,它将解决你的问题。

添加程序包。

开放命名空间:

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);

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

需要注意的是,不受约束的工具虽然非常有效地解决了隔离问题,但通过这种方式,它们可以原谅设计错误,最终可能导致糟糕的应用程序架构。

完全不使用Moq怎么样
您可以创建一个包装器类,该类派生自您的主类,并使用所需的任何方法覆盖您想要模拟的方法
然后在测试中使用这个派生类
当然,这些overriden方法可以使用Moq,也可以定义为此派生类中的mock。

最新更新