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.