简体   繁体   中英

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. 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. I want it to return a memory only ISettings instance to accelerate my test.

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. 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.

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. 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:

[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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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