I am trying to mock the two interfaces below.
Mock<IEmailSender> emailSender = new Mock<IEmailSender>();
Mock<IEmailTemplate> emailTemplate = new Mock<IEmailTemplate>();
Here is the setup
emailTemplate.Setup(x => x.GetForgotPasswordTemplate(It.IsAny<EmailTemplateViewModel>())).Returns(It.IsAny<string>());
emailSender.Setup(x => x.SendEmailAsync(It.IsAny<SendEmailViewModel>(), default)).ReturnsAsync(It.IsAny<SendEmailResultViewModel>());
Here is the controller action that is called.
[EnableCors(PolicyName = "AllowClientAccess")]
[HttpGet("Forgot")]
public async Task<IActionResult> ForgotPassword([FromQuery] string email)
{
var user = await _userManager.FindByEmailAsync(email);
if (user != null)
{
//MOQ file path not found
EmailTemplateViewModel model = new EmailTemplateViewModel();
model.Email = email;
model.RecipientName = user.UserName;
var message = _emailTemplate.GetForgotPasswordTemplate(model);
SendEmailViewModel sendEmailViewModel = new SendEmailViewModel();
sendEmailViewModel.RecipientName = user.UserName;
sendEmailViewModel.RecipientEmail = user.Email;
sendEmailViewModel.Subject = "ForgotPassword";
sendEmailViewModel.Body = message;
await _emailSender.SendEmailAsync(sendEmailViewModel);
return Ok(AddSuccess("Check your email", "Forgot Password"));
}
ModelState.AddModelError("Forgot Password","Unable to send email");
return BadRequest(ModelErrors());
}
This line returns null
var message = _emailTemplate.GetForgotPasswordTemplate(model);
Here is the method code
public string GetForgotPasswordTemplate(EmailTemplateViewModel model)
{
try
{
var utcNow = DateTime.Now;
if (_testEmailTemplate == null)
if (File.Exists("Helpers/Templates/ForgotPasswordEmail.template"))
_testEmailTemplate = ReadPhysicalFile("Helpers/Templates/ForgotPasswordEmail.template");
var appUrl = _configuration.GetSection("ApplicationUrl").Value +
"/reset-password?&email=" + model.Email;
var emailMessage = _testEmailTemplate
.Replace("{user}", model.RecipientName)
.Replace("{testDate}", utcNow.ToString(CultureInfo.InvariantCulture))
.Replace("{appUrl}", appUrl);
return emailMessage;
}
catch (Exception e)
{
Log.Warning(e, "Email error");
throw;
}
}
This line also returns null
await _emailSender.SendEmailAsync(sendEmailViewModel);
Here is the method code
public Task<SendEmailResultViewModel> SendEmailAsync(SendEmailViewModel model, SmtpConfig config = default)
{
model.IsHtml = true;
var from = new MailboxAddress(_config.FromName, _config.FromEmail);
var to = new MailboxAddress(model.RecipientName, model.RecipientEmail);
return SendEmailAsync(@from, new[] {to}, model.Body, model.Body, config, model.IsHtml);
}
Here is the test
[Theory]
[InlineData("stephen@kaizenappz.com")]
public async Task WhenAUserForgetsPasswordAHttpStatusCode200ShouldBeReturnedAsync(string email)
{
var confirmUser = await Controller.ForgotPassword(email);
var result = confirmUser as OkObjectResult;
var actual = (HttpStatusCode)result?.StatusCode.Value;
var expected = HttpStatusCode.OK;
Assert.AreEqual(expected, actual);
}
However the test passes and what i am wondering is why do both of these methods return null and why does the test pass even though it returns null. How do i get these to return something?
One thing I do not understand is when to use It.Any and just pass in a normal object with some test data. How am i supposed to check a user exists if i use It.Any and i need to pass a model into my controller action?