简体   繁体   English

最小起订量-模拟.Object.MyMethod模拟不起作用

[英]Moq - mock.Object.MyMethod mocking does not work

I have a strange trouble. 我有一个奇怪的麻烦。 I am not too familiar with Moq, being more a GUI guy. 我对Moq不太熟悉,更是一名GUI用户。 I tried to mock a factory method in my code. 我试图在代码中模拟工厂方法。 The factory looks like this, and returns a ISettings instance which does many IO Operations. 工厂看起来像这样,并返回一个执行许多IO操作的ISettings实例。 I want it to return a memory only ISettings instance to accelerate my test. 我希望它只返回一个内存ISettings实例以加快测试速度。

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

and the mock is 而模拟是

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

the tryToSeeTheType is however XMLSettings and not NonPersistingSettings as I would expect. tryToSeeTheType是XMLSettings,而不是我所期望的NonPersistingSettings。 Stepping through results into the code shown me that it goes directly into the original factory method. 单步执行结果到代码中,向我展示了它直接进入原始工厂方法。 Any suggestions what I do wrong here? 有什么建议我在这里做错了吗?

The "Object" property of a mocked object is not actually an instance of the class you are trying to mock. 模拟对象的“ Object”属性实际上不是您要模拟的类的实例。

The purpose of a mock is to be able to replace an object the method you are trying to test depends on. 模拟的目的是能够替换您要测试的方法所依赖的对象。

Imagine that your SettingsFactory performs very expensive operations like for example accessing the network or a database or the file system. 想象一下,您的SettingsFactory执行非常昂贵的操作,例如访问网络,数据库或文件系统。 You do not want your test to access those expensive resources so you create a mock. 您不希望测试访问那些昂贵的资源,所以您创建了一个模拟。 I would be something like this: 我会是这样的:

public class ClassThatUsesSettingsFactory
{
    private readonly SettingsFactory _settingsFactory;

    public ClassThatUsesSettingsFactory(SettingsFactory settingsFactory)
    {
       _settingsFactory = settingsFactory;
    }

    public void MethodThatCallsSettingsFactory()
    {
       //... do something
       var settings = _settingsFactory.CreateOrGetSettings();
       //... do something
    }
}

By doing this you are able to replace the SettingsFactory with a mock on your unit test like so: 这样,您就可以用单元测试中的模拟代替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();
}

This unit test is basically only making sure that the method CreateOrGetSettings gets called once and only once when the MethodThatCallsSettingsFactory gets executed. 基本上,此单元测试仅确保方法CreateOrGetSettings被调用一次,并且仅在执行MethodThatCallsSettingsFactory时调用一次。

What Moq does is to create a different class with a different implementation of its virtual method that will, most likely, set a flag to true once it gets called and then check the value of that flag on the "Verify" method. Moq所做的是用其虚拟方法的不同实现创建一个不同的类,该类很可能会在调用后将标志设置为true,然后在“ Verify”方法上检查该标志的值。

There is a lot to grasp here so I hope it is clear enough since you mentioned that you do not have a lot of experience with Moq. 这里有很多要把握的地方,所以我希望它很清楚,因为您提到您对Moq的经验不足。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM