简体   繁体   中英

How do I use moq to assert a function is called in c#?

I am trying to learn how to use Moq to do unit testing with C#. I setup a simple class, BasicMath that has a function int Multiply(int a, int b) , the body just returns a * b. I have another class called AdvancedMath which has a function 'int Square(int a)', the body calls Multiply(a,a) and returns the result.

I am trying to write a simple test for AdvancedMath.Square that will assert that BasicMath.Multiply is called with the correct values. I understand that you cannot do this with ordinary public function so I made the functions virtual, but I am still having trouble. Can someone explain to me how this is done? Neither class has any constructor other than the default empty constructor.

Here is my attempt:

class test_Advanced_Functions
{
    [Test]
    public void test_SquareFunction_Should_return_correct_result()
    {
        // Arrange
        Mock<BasicFunctions> mock = new Mock<BasicFunctions>();
        AdvancedFunctions af = new AdvancedFunctions();

        // Act
        int result = af.Square(5);

        //Assert
        mock.Verify(d => d.Multiply(5, 5), Times.Exactly(1));
    }

Assuming AdvancedMath derives from BasicMath then you can test that with Moq when Multiply is virtual:

var mock = new Mock<AdvancedMath>();
mock.Setup(m => m.Multiply(2, 2)).Returns(4);
mock.Object.Square(2);
mock.VerifyAll();

If you use BasicMath within AdvancedMath (ie. if Multiply is static and is invoked directly from Square ), then testing such interaction is not possible with Moq. To see why, see this question .

However, doing behavior based verification in such simple case doesn't seem right. You need to answer yourself a question: "what do I want to test?" . That Square works or that it calls some methods? This test (what you plan to do now), only delegates responsibility to Multiply , assuming it works. Your Square implementation might change in multiple ways (as in, not using Multiply ) and it will break your test - it shouldn't.

Moq cannot modify behavior of instances that it has not created.

You should write your classes to be unit-testable by practicing dependency injection. Since AdvancedFunctions apparently depends on BasicFunctions , it should have a BasicFunctions passed in as a constructor argument, rather than new ing one up on its own.

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