Moq-mock.Object.MyMethod嘲讽不起作用

本文关键字:不起作用 MyMethod Object Moq-mock | 更新日期: 2023-09-27 18:28:23

我遇到了一个奇怪的麻烦。我不太熟悉Moq,更像是一个GUI的家伙。我试图在代码中模拟一个工厂方法。工厂看起来是这样的,并返回一个执行许多IO操作的ISettings实例。我希望它返回一个只有内存的ISettings实例来加速我的测试。

public class SettingsFactory
{
    internal ISettings mSettingsImpl;
    internal virtual ISettings CreateOrGetSettings()
    {
        return mSettingsImpl ?? (mSettingsImpl = new XmlSettings());
    }
}

模拟是

var imocked = new Mock<SettingsFactory>() {CallBase = false};
imocked.Setup(x => x.CreateOrGetSettings()).Returns(new NonPersistingSettings());
var tryToSeeTheType = imocked.Object.CreateOrGetSettings();

tryToSeeTheType是XMLSettings,而不是我所期望的NonPersistingSettings。将结果逐步输入到代码中,这表明它直接进入了原始的工厂方法。有什么建议我做错了什么吗?

Moq-mock.Object.MyMethod嘲讽不起作用

模拟对象的"Object"属性实际上并不是要模拟的类的实例。

mock的目的是能够替换您试图测试的方法所依赖的对象。

想象一下,您的SettingsFactory执行非常昂贵的操作,例如访问网络、数据库或文件系统。您不希望您的测试访问那些昂贵的资源,所以您创建了一个mock。我会是这样的:

public class ClassThatUsesSettingsFactory
{
    private readonly SettingsFactory _settingsFactory;
    public ClassThatUsesSettingsFactory(SettingsFactory settingsFactory)
    {
       _settingsFactory = settingsFactory;
    }
    public void MethodThatCallsSettingsFactory()
    {
       //... do something
       var settings = _settingsFactory.CreateOrGetSettings();
       //... do something
    }
}

通过这样做,您可以在单元测试中用模拟来替换SettingsFactory,如下所示:

[TestMethod]
public void MakeSureSettingsFactoryIsCalled()
{
   var settingsFactoryMock = new Mock<SettingsFactory>();
   settingsFactoryMock.Setup(f => f.CreateOrGetSettings(), Times.Once).Verifiable();
   var subjectUnderTest = new ClassThatUsesSettingsFactory(settingsFactoryMock.Object);
   subjectUnderTest.MethodThatCallsSettingsFactory();
   settingsFactoryMock.Verify();
}

这个单元测试基本上只确保方法CreateOrGetSettings被调用一次,并且在MethodThatCallsSettingsFactory被执行时只调用一次。

Moq所做的是用其虚拟方法的不同实现创建一个不同的类,该方法很可能在调用后将标志设置为true,然后在"Verify"方法上检查该标志的值。

这里有很多东西需要把握,所以我希望这一点足够清楚,因为你提到你在Moq方面没有太多经验。