James Radford
James Radford

Reputation: 1855

how to assert if a method has been called using nunit

is it possible to assert whether a method has been called? I'm testing the following method and I want to assert that the _tokenManager.GetToken() has been called. I just want to know if the method has been called as the method does not return a value. I am using Moq.

Thanks,

Code snippet

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

Upvotes: 29

Views: 55884

Answers (2)

Dariusz Woźniak
Dariusz Woźniak

Reputation: 10350

You should mock TokenManager and TokenValidator, and then create two unit test cases:

  • Case 1: token is validated and GetToken is called exactly once
  • Case 2: token is not validated and GetToken is called exactly twice

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

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

Alternatively, you can create an unit test without mocking TokenValidator and verify if GetToken() has been called at least once. However, creating two cases as in the first example is preferred as we are testing all code paths.

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

Read more about verification in Moq at:

Upvotes: 24

Jack Hughes
Jack Hughes

Reputation: 5664

You can verify using MOQ using the Verify method. Like this:

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

You need to be able to pass the token manager into your system under test somehow. Usually via the ctor or maybe a property.

I would suggest you use something like AutoFixture to remove the ugliness that is "ssss" and make things a bit more DRY.

You may need to make the token manager mock return something appropriate too that will pass the validation. Something like this:

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

Upvotes: 9

Related Questions