Using Moq to determine if a method is called

C#.NetUnit TestingMockingMoq

C# Problem Overview


It is my understanding that I can test that a method call will occur if I call a higher level method, i.e.:

public abstract class SomeClass()
{    
    public void SomeMehod()
    {
        SomeOtherMethod();
    }

    internal abstract void SomeOtherMethod();
}

I want to test that if I call SomeMethod() then I expect that SomeOtherMethod() will be called.

Am I right in thinking this sort of test is available in a mocking framework?

C# Solutions


Solution 1 - C#

You can see if a method in something you have mocked has been called by using Verify, e.g.:

static void Main(string[] args)
{
        Mock<ITest> mock = new Mock<ITest>();
    
        ClassBeingTested testedClass = new ClassBeingTested();
        testedClass.WorkMethod(mock.Object);

        mock.Verify(m => m.MethodToCheckIfCalled());
}

class ClassBeingTested
{
    public void WorkMethod(ITest test)
    {
        //test.MethodToCheckIfCalled();
    }
}

public interface ITest
{
    void MethodToCheckIfCalled();
}

If the line is left commented it will throw a MockException when you call Verify. If it is uncommented it will pass.

Solution 2 - C#

No, mock testing assumes you are using certain testable design patterns, one of which is injection. In your case you would be testing SomeClass.SomeMethod and SomeOtherMethod must be implemented in another entity which needs to be interfaced.

Your Someclass constructor would look like New(ISomeOtherClass). Then you would mock the ISomeOtherClass and set expectation on its SomeOtherMethod to be called and verify the expectation.

Solution 3 - C#

Even though I agree that the @Paul's answer is the recommended way to go I just want to add one alternative way which is provided by moq off the self.

Since SomeClass is abstract it is indeed mockable, but public void SomeMehod() isn't. The point is to find the way to mock and somehow invoke that method and then using CallBase propagate the call to the SomeOtherMethod(). It might sound as a hack but it is simple in essence. It could be used in the case if the proposed refactoring is not possible.

// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
    public virtual void DummyMethod() => base.SomeMethod();
}

Then you could setup DummyMethod() to propagate the call by setting CallBase flag.

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();

//Act
mock.Object.SomeMethod();

//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOwenView Question on Stackoverflow
Solution 1 - C#PaulView Answer on Stackoverflow
Solution 2 - C#ValView Answer on Stackoverflow
Solution 3 - C#JohnnyView Answer on Stackoverflow