Reputation: 1443
I am trying to unit test a controller that returns an IActionResult but can also throw an exception in certain circumstances. The problem I am running into is I'm not sure how to call it as the Assert throws an error where you cannot convert from IActionResult to Action.
How would I go about testing below statement?
Assert.Throws<Exception>(await controller.SendEmail(email)); //how to test this
I looked through the Microsoft testing controller documentation and didn't find something relevant. Most examples I see testing exceptions are for things like accessing repositories or services.
I understand I can return a badrequest or redirect to the page with an error message. But is what I am trying to accomplish possible?
My HomeController Method
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SendEmail(EmailModel emailModel)
{
if(!ModelState.IsValid)
{
return View("Index",emailModel);
}
var response = await _sendEmail.SendEmailMessage(emailModel);
if (response != System.Net.HttpStatusCode.Accepted)
{
throw new Exception("Email failed to send, please try again later");
}
else
{
TempData["message"] = $"Email has been sent";
}
return RedirectToAction("Index");
}
XUnit HomeControllerTest Constructor for arrange
private Mock<ISendEmail> mockSendEmail;
private HomeController controller;
public HomeControllerShould()
{
mockSendEmail = new Mock<ISendEmail>();
mockSendEmail.Setup(x => x.SendEmailMessage(It.IsAny<EmailModel>())).ReturnsAsync(HttpStatusCode.Accepted);
controller = new HomeController(mockSendEmail.Object);
}
XUnit Test for Sending Email
[Fact]
public async Task SendEmailActionThrowsExceptionOnEmailFailure()
{
mockSendEmail.Setup(x => x.SendEmailMessage(It.IsAny<EmailModel>())).ReturnsAsync(HttpStatusCode.InternalServerError);
var email = new EmailModel();
Assert.Throws<Exception>(await controller.SendEmail(email)); //how to test this
}
Upvotes: 0
Views: 1590
Reputation: 62260
Assert.Throws
requires a function. You could use ThrowsAsync
.
[Fact]
public async Task SendEmailActionThrowsExceptionOnEmailFailure()
{
mockSendEmail.Setup(x => x.SendEmailMessage(It.IsAny<EmailModel>()))
.ReturnsAsync(HttpStatusCode.InternalServerError);
var email = new EmailModel();
await Assert.ThrowsAsync<Exception>(() => controller.SendEmail(email));
}
FYI: We don't normally return HttpStatusCode
from service layer such as email service, but I'll let you decide.
Upvotes: 2