developer tip

Moq에서 메서드가 정확히 한 번 호출되었는지 어떻게 확인합니까?

optionbox 2020. 8. 15. 09:04
반응형

Moq에서 메서드가 정확히 한 번 호출되었는지 어떻게 확인합니까?


Moq에서 메서드가 정확히 한 번 호출되었는지 어떻게 확인합니까? Verify()대의 Verifable()일이 정말 혼란.


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 -모의 메소드가 정확히 한 번 호출되도록 지정합니다.

메소드 호출이라는 것을 기억하십시오. 나는 그들이 속성이라고 생각하고 괄호를 잊어 버리고 계속 넘어졌습니다.


정수 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);
    }
}

Note: By default Moq will stub all the properties and methods as soon as you create a Mock object. So even without calling Setup, Moq has already stubbed the methods for IPrinter so you can just call Verify. However, as a good practice, I always set it up because we may need to enforce the parameters to the method to meet certain expectations, or the return value from the method to meet certain expectations or the number of times it has been called.


Test controller may be :

  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);
    }

And When DeleteCars method called with valid id, then we can verify that, Service remove method called exactly once by this test :

 [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));
    }

참고URL : https://stackoverflow.com/questions/4206193/how-do-i-verify-a-method-was-called-exactly-once-with-moq

반응형