Как проверить, что метод был вызван ровно один раз с Moq? - PullRequest
99 голосов
/ 17 ноября 2010

Как проверить, что метод был вызван ровно один раз с Moq? Verify() против Verifable() вещь действительно сбивает с толку.

Ответы [ 3 ]

145 голосов
/ 17 ноября 2010

Вы можете использовать Times.Once() или Times.Exactly(1):

mockContext.Verify(x => x.SaveChanges(), Times.Once());
mockContext.Verify(x => x.SaveChanges(), Times.Exactly(1));

Вот методы класса Times :

  • AtLeast - Указывает, что макетируемый метод должен вызываться как минимум раз.
  • AtLeastOnce - Указывает, что макетируемый метод должен вызываться как минимум один раз.
  • AtMost - Указывает, что макетируемый метод должен вызываться максимально раз.
  • AtMostOnce - указывает, что макетируемый метод должен вызываться максимум один раз.
  • Between - Указывает, что проверяемый метод должен вызываться между и временем.
  • Exactly - Указывает, что макетный метод должен вызываться ровно раз.
  • Never - Указывает, что макетный метод не должен вызываться.
  • Once - Указывает, что смоделированный метод должен вызываться ровно один раз.

Просто помните, что они являются вызовами методов; Меня все время обманывают, думая, что это собственность, и забывая о скобках.

6 голосов
/ 09 апреля 2018

Представьте, что у нас есть калькулятор с одним методом для добавления 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. Однако, как хорошая практика, я всегда настраиваю его, потому что нам может потребоваться принудительное применение параметров метода для удовлетворения определенных ожиданий или возвращаемого значения метода для удовлетворения определенных ожиданий.

2 голосов
/ 14 декабря 2016

Тестовый контроллер может быть:

  public HttpResponseMessage DeleteCars(HttpRequestMessage request, int id)
    {
        Car item = _service.Get(id);
        if (item == null)
        {
            return request.CreateResponse(HttpStatusCode.NotFound);
        }

        _service.Remove(id);
        return request.CreateResponse(HttpStatusCode.OK);
    }

И когда метод DeleteCars вызывается с действительным идентификатором, мы можем убедиться в том, что метод удаления службы вызывается ровно один раз с помощью этого теста:

 [TestMethod]
    public void Delete_WhenInvokedWithValidId_ShouldBeCalledRevomeOnce()
    {
        //arange
        const int carid = 10;
        var car = new Car() { Id = carid, Year = 2001, Model = "TTT", Make = "CAR 1", Price=2000 };
        mockCarService.Setup(x => x.Get(It.IsAny<int>())).Returns(car);

        var httpRequestMessage = new HttpRequestMessage();
        httpRequestMessage.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration();

        //act
        var result = carController.DeleteCar(httpRequestMessage, vechileId);

        //assert
        mockCarService.Verify(x => x.Remove(carid), Times.Exactly(1));
    }
...