Adam Mendoza
Adam Mendoza

Reputation: 5903

How do I get a result from this mocked service?

How do I get a result from a mocked service? Note: It works properly. I'm just trying to get the test going.

The service:

    public interface ISendgridService
{
    Task<Response> SendAsync(IEmailMessage emailMessage);
}

// The test

        [TestMethod]
    public async Task SendEmailTest()
    {
        // Arrange
        var mockSendgrid = new Mock<ISendgridService>();

        var response = new Mock<Func<SendGrid.Response>>();

        mockSendgrid.Setup(s => s.SendAsync(It.IsAny<IEmailMessage>()))
            .ReturnsAsync(response.Object.Invoke);

        var emailMessage = _builder.CreateNew<EmailMessage>()
            .With(e => e.From = _sendgridConfiguration.SenderEmail)
            .With(e => e.FromName = _sendgridConfiguration.SenderName)
            .With(e => e.To = Faker.Internet.Email())
            .Build();


        // Act
        var result = await mockSendgrid.Object.SendAsync(emailMessage);

        // Assert
     // result is null // How do I get a value?
    }

Upvotes: 0

Views: 674

Answers (3)

Scott Hannen
Scott Hannen

Reputation: 29312

You've set up the Mock<ISendgridService> to return something - it uses another mock - Mock<Func<SendGrid.Response>> and returns the result of invoking that Func.

But you haven't set up the Mock<Func<SendGrid.Response>> to return anything, so it doesn't.

In other words, when you do this:

mockSendgrid.Setup(s => s.SendAsync(It.IsAny<IEmailMessage>()))
    .ReturnsAsync(response.Object.Invoke);

What does response.Object.Invoke return? response.Object is a Mock<Func<SendGrid.Response>>, but it hasn't been set up to return anything.

A Func is actually much easier to mock without using Moq. You can just do this:

// Create the thing you need the function to return, whatever that looks like.
var response = new SendGrid.Response(someStatusCode, body, headers); 

// create a function that returns it.
var functionMock = new Func<SendGrid.Response>(() => response);

Upvotes: 1

nalnpir
nalnpir

Reputation: 1193

That depends on what you want to test of the app, if you are trying to test whether it sends an email or not, you shouldnt be using a mock class if you want to actually test if it sends. What you should mock is the content of the email.

Now if what you want to check is that certain steps including the email works (integrating all of them in a method) thats another matter, in this case you should use a dummy task that returns a dummy response.

Upvotes: 0

Robert Swilley
Robert Swilley

Reputation: 502

I am a little confused as to what you're trying to test. Usually, you'd act on a concrete class under test, not a stubbed object.

Pseudo code below:

public class SendGridService : ISendGridService {
  public async Task<bool> SendAsync() {
    //code that sends the email
  }
}

Your test would be like:

//Act
var subject = new SendGridService();
var result = await subject.SendAsync();

//Assert
Assert.IsTrue(result);

Upvotes: 3

Related Questions