Представьте, что у нас есть калькулятор с одним методом для добавления 2 целых чисел. Давайте теперь представим, что при вызове метода add он вызывает метод print один раз. Вот как мы можем это проверить:
public interface IPrinter
{
void Print(int answer);
}
public class ConsolePrinter : IPrinter
{
public void Print(int answer)
{
Console.WriteLine("The answer is {0}.", answer);
}
}
public class Calculator
{
private IPrinter printer;
public Calculator(IPrinter printer)
{
this.printer = printer;
}
public void Add(int num1, int num2)
{
printer.Print(num1 + num2);
}
}
А вот фактический тест с комментариями в коде для дальнейшего уточнения:
[TestClass]
public class CalculatorTests
{
[TestMethod]
public void WhenAddIsCalled__ItShouldCallPrint()
{
/* Arrange */
var iPrinterMock = new Mock<IPrinter>();
// Let's mock the method so when it is called, we handle it
iPrinterMock.Setup(x => x.Print(It.IsAny<int>()));
// Create the calculator and pass the mocked printer to it
var calculator = new Calculator(iPrinterMock.Object);
/* Act */
calculator.Add(1, 1);
/* Assert */
// Let's make sure that the calculator's Add method called printer.Print. Here we are making sure it is called once but this is optional
iPrinterMock.Verify(x => x.Print(It.IsAny<int>()), Times.Once);
// Or we can be more specific and ensure that Print was called with the correct parameter.
iPrinterMock.Verify(x => x.Print(3), Times.Once);
}
}
Примечание : по умолчанию Moq отключит все свойства и методы, как только вы создадите объект Mock. Поэтому, даже не вызывая Setup
, Moq уже заглушил методы для IPrinter
, поэтому вы можете просто вызвать Verify
. Однако, как хорошая практика, я всегда настраиваю его, потому что нам может потребоваться принудительное применение параметров метода для удовлетворения определенных ожиданий или возвращаемого значения метода для удовлетворения определенных ожиданий.