Leomar de Souza
Leomar de Souza

Reputation: 757

Moq: Verify method for methods with overloads

I am implementing a test to check a method of sending email that is found in a service.

[Fact]
public async Task MailService_SendMailMime_WhenItsOk()
{
    //Arrange
    var message = new MimeMessage
    {
        Subject = "My test message",
        Body = new TextPart("html")
        {
            Text = "Test"
        }
    };
    message.From.Add(new MailboxAddress("Collection System", "[email protected]"));
    message.To.Add(new MailboxAddress("User", "[email protected]"));


    //Act
    await _mailService.SendMailMimeAsync(message);

    //Assert
    _mocker.GetMock<ISmtpClient>().Verify(r => r.SendAsync(message, It.IsAny<MailboxAddress>(), It.IsAny<IEnumerable<MailboxAddress>>(), CancellationToken.None, It.IsAny<ITransferProgress>()), Times.Never);
}

The method I want to test:

public async Task SendMailMimeAsync(MimeMessage message)
{
    try
    {
        var smtpHost = "mysmpthost.com" ;

        using (_smtpClient)
        {
            await _smtpClient.ConnectAsync(smtpHost, 25, false);
            await _smtpClient.SendAsync(message);
        }

        _logger.LogInformation($"SMTP message sent to {message.To}");
    }
    catch (Exception ex)
    {
        _logger.LogInformation($"There was a error while sending a SMTP message to {message.To}");
    }
}

With that, I tried to use Verify() to check if the SendAsync() method was called at least once. However, as he has method overloads, I only succeeded in the test by pointing out that he was never called (Times.Never). The _smtpClient it's a class of MailKit.Net.Smtp. In this link you can view your methods: http://www.mimekit.net/docs/html/T_MailKit_Net_Smtp_SmtpClient.htm.

As this method has several possibilities of overloads, I don't know how best to test it.

Upvotes: 1

Views: 822

Answers (1)

Peter Csala
Peter Csala

Reputation: 22849

The MailKit's IMailTransport interface defines several overloads for SendAsync:

Task SendAsync(
      MimeMessage message,
      CancellationToken cancellationToken = default (CancellationToken),
      ITransferProgress progress = null);

Task SendAsync(
      MimeMessage message,
      MailboxAddress sender,
      IEnumerable<MailboxAddress> recipients,
      CancellationToken cancellationToken = default (CancellationToken),
      ITransferProgress progress = null);

Task SendAsync(
      FormatOptions options,
      MimeMessage message,
      CancellationToken cancellationToken = default (CancellationToken),
      ITransferProgress progress = null);

Task SendAsync(
      FormatOptions options,
      MimeMessage message,
      MailboxAddress sender,
      IEnumerable<MailboxAddress> recipients,
      CancellationToken cancellationToken = default (CancellationToken),
      ITransferProgress progress = null);

When you call the SendAsync like this: SendAsync(message)
then it will resolve this call to the following overload:

Task SendAsync(
      MimeMessage message,
      CancellationToken cancellationToken = default (CancellationToken),
      ITransferProgress progress = null);

That means the following two calls are equvivalent:

SendAsync(message);

SendAsync(message, default, default);

So, your Verify statement should look like this:

[Fact]
public async Task MailService_SendMailMime_WhenItsOk()
{
    //Arrange
    var _smtpClientMock = new Mock<ISmtpClient>();
    var _mailService = new MailService(_smtpClientMock.Object);

    var message = new MimeMessage
    {
        Subject = "My test message",
        Body = new TextPart("html")
        {
            Text = "Test"
        }
    };

    //Act
    await _mailService.SendMailMimeAsync(message);

    //Assert
    _smtpClientMock.Verify(client => client.SendAsync(message, default, default), Times.Once);
}

Upvotes: 3

Related Questions