Question

This seems like something simple but I can't seem to get it to work.

I have a class with a Save method that simply calls another method ShouldBeCalled(). I want to verify that if I call Save() that the other method ShouldBeCalled() is executed at least once. I thought that I could do the following.

public class ClassA
{
    public virtual void Save()
    {
        ShouldBeCalled();
    }

    public virtual void ShouldBeCalled()
    {
        //This should get executed
    }
}

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_Should_Call_ShouldBeCalled()
    {
        var mockClassA = new Mock<ClassA>();
        mockClassA.Object.Save();

        mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
    }
}

But I get the exception "Expected invocation on the mock at least once, but was never performed: x => x.ShouldBeCalled()"

It is just a guess but Is Moq overriding the Save() method with it's own version which ignores anything I have inside the real object's Save() method.

Was it helpful?

Solution

You are having this problem because you are mocking what you are testing. This doesn't make sense.

You are correct that Moq will replace the implementation of your method with its own. The reason is you are supposed to use Moq to mock things the class you are testing calls, not the class you are testing itself.

This test would be appropriate if your code were designed thusly:

public class ClassA
{
    BusinessLogicClass bl;
    public ClassA(BusinessLogicClass bl)
    {
         this.bl = bl;
    }

    public void Save()
    {
        bl.ShouldBeCalled();
    }
}

public class BusinessLogicClass
{
    public virtual void ShouldBeCalled()
    {
        //This should get executed
    }
}

And here is the correct test of that method now:

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_ShouldCallShouldBeCalled()
    {
        //Arrange
        var mockBLClass = new Mock<BusinessLogicClass>();
        mockBLClass.Setup(x => x.ShouldBeCalled()).Verifyable();

        //Act    
        ClassA classA = new ClassA(mockBLClass.Object);
        classA.Save();

        //Assert
        mockBLClass.VerifyAll();
    }
}

The key lesson here is that you mock/stub what your test needs to run, not what you are testing itself.

Hope this helps, Anderson

OTHER TIPS

Try using the CallBase = true and then false. I ran your code and it works.

var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true;
mockClassA.Object.Save();
mockClassA.CallBase = false;
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());

Yes, this can be done. However, you need to add a line of code to have Moq track whether or not the ShouldBeCalled method was indeed called.

Something like the following will work:

var mockClassA = new Mock<ClassA>();
mockClassA.Setup(x => x.ShouldBeCalled()).Verifiable();    
mockClassA.Object.Save();    
mockClassA.Verify(x => s.ShouldBeCalled(), Times.AtLeastOnce());

The Setup method sets up expectations. When you call Verify, you are asking Moq to verify these expectations. If you don't make a Setup call to create expectations for the ShouldBeCalled method, then Moq doesn't consider it to be trackable and will therefore fail hard when you try to Verify it.

You can stub methods in the system under test using CallBase.

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_Should_Call_ShouldBeCalled()
    {
        // Arrange
        var mockClassA = new Mock<ClassA>();
        mockClassA.CallBase = true; // this will call real methods unless the method is mocked/stubbed. 
        mockClassA.Setup(a => a.ShouldBeCalled());

        // Act
        mockClassA.Save();

        // Assert
        mockClassA.Verify(a => a.ShouldBeCalled(), Times.Once());
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top