Как утверждать, был вызван метод с помощью nunit

Можно ли утверждать, был ли вызван метод? Я тестирую следующий метод, и я хочу утверждать, что был вызван _tokenManager.GetToken(). Я просто хочу знать, был ли метод вызван как метод, который не возвращает значение. Я использую Moq.

Спасибо,

Фрагмент кода

public void Subscribe(string code, string emailAddress, string columnKey)
{
    // Request authentication token
    var token = _tokenManager.GetToken(code, false);

    if (!_tokenValidator.Validate(token))
    {
        // Token has expired or invalid - refresh the token 
        token = _tokenManager.GetToken(code, true);
    }

    // Subscribe email
    _silverpopRepository.Subscribe(token.AccessToken, emailAddress, columnKey);
}

Ответ 1

Вы должны высмеять TokenManager и TokenValidator, а затем создать два случая unit test:

  • Случай 1: токен проверен и GetToken вызывается ровно один раз
  • Случай 2: токен не проверен, а GetToken вызывается ровно дважды

Случай 1:

[Test]
public void Subscribe_TokenIsValidated_GetTokenIsCalledOnce()
{
    // Arrange:
    var tokenManagerMock = Mock.Of<TokenManager>();

    var tokenValidatorMock = Mock.Of<TokenValidator>(x =>
        x.Validate(It.IsAny<Token>()) == true);

    var subscriber = new Subscriber
    {
        TokenManager = tokenManagerMock,
        TokenValidator = tokenValidatorMock
    };

    // Act:
    subscriber.Subscribe(It.IsAny<string>(), It.IsAny<string>(),
        It.IsAny<string>());

    // Assert:
    Mock.Get(tokenManagerMock).Verify(x =>
        x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.Once);
}

Случай 2:

[Test]
public void Subscribe_TokenIsExpiredOrInvalid_GetTokenIsCalledTwice()
{
    // Arrange:
    var tokenManagerMock = Mock.Of<TokenManager>();

    var tokenValidatorMock = Mock.Of<TokenValidator>(x =>
        x.Validate(It.IsAny<Token>()) == false);

    var subscriber = new Subscriber
    {
        TokenManager = tokenManagerMock,
        TokenValidator = tokenValidatorMock
    };

    // Act:
    subscriber.Subscribe(It.IsAny<string>(), It.IsAny<string>(),
        It.IsAny<string>());

    // Assert:
    Mock.Get(tokenManagerMock).Verify(x =>
        x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.Exactly(2));
}

В качестве альтернативы вы можете создать unit test без насмешивания TokenValidator и проверить, был ли вызов GetToken() хотя бы один раз. Тем не менее, создание двух случаев, как в первом примере, является предпочтительным, поскольку мы тестируем все пути кода.

// Arrange:
var tokenManagerMock = Mock.Of<TokenManager>();
var subscriber = new Subscriber {TokenManager = tokenManagerMock};

// Act:
subscriber.Subscribe(It.IsAny<string>(),
    It.IsAny<string>(),
    It.IsAny<string>());

// Assert:
Mock.Get(tokenManagerMock).Verify(x =>
        x.GetToken(It.IsAny<string>(), It.IsAny<bool>()), Times.AtLeastOnce);

Узнайте больше о проверке в Moq at:

Ответ 2

Вы можете проверить использование MOQ с помощью метода Verify. Вот так:

var tokenManagerMock = new Mock<ITokenManager>();
var sut = new WhateverItIsCalled(tokenManagerMock.Object);
sut.Subscribe("ssss", "[email protected]", "XXX");
tokenManagerMock.Verify(m => m.GetToken(It.Is<string>(c => c == "ssss", It.Is<bool>(x => x == false)), Times.Once); 

Вы должны иметь возможность как можно скорее передать менеджер токенов в вашу систему. Обычно через ctor или, возможно, собственность.

Я бы предложил вам использовать что-то вроде AutoFixture, чтобы удалить уродство, которое является "ssss", и сделать вещи немного более сухими.

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

var tokenManagerMock = new Mock<ITokenManager>();
tokenManagerMock.Setup(m => m.GetToken(It.Is<string>(x => x == "ssss", It.IsAny<bool>()).Returns("XXXXXX");