Reputation: 5903
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
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
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
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