PixelPaul
PixelPaul

Reputation: 2767

.NET Core Unit Test Razor Pages RedirectToPage()

I'm writing a unit test using MSTest and Moq for the following Razor Page handler method:

public async Task<IActionResult> OnPostAsync()
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByEmailAsync(Input.Email);

        if (user == null)
        {
            return Page();
        }

        // Trying to unit test this code here
        if (!await _userManager.IsEmailConfirmedAsync(user))
        {
            return RedirectToPage("/Account/EmailNotConfirmed");
        }

        var code = await _userManager.GeneratePasswordResetTokenAsync(user);
        code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
        var callbackUrl = Url.ResetPasswordCallbackLink(user.Id.ToString(), code, Request.Scheme);
        var callbackLink = HtmlEncoder.Default.Encode(callbackUrl);

        await _emailService.SendRazorTemplateEmailAsync(Input.Email, EmailTemplate.ResetPassword, new {Link = callbackUrl});

        return RedirectToPage("/Account/ForgotPasswordSuccess", new { email = Input.Email });
    }

    return Page();
}

I'm trying to write a unit test for the code block where await _userManager.IsEmailConfirmedAsync(user) returns false and RedirectToPage(). Here is my unit test code:

private Mock<IEmailService>  _emailService;
private Mock<ILogger<ForgotPasswordModel>>  _logger;
private Mock<UserManager<ApplicationUser>> _userManager;
private Mock<IUserStore<ApplicationUser>> _userStore;
private ForgotPasswordModel _pageModel;

public ForgotPasswordTests()
{
    _emailService = new Mock<IEmailService>();
    _logger = new Mock<ILogger<ForgotPasswordModel>>();
    _userStore = new Mock<IUserStore<ApplicationUser>>();
    _userManager = new Mock<UserManager<ApplicationUser>>(_userStore.Object, null, null, null, null, null, null, null, null);
    _pageModel = new ForgotPasswordModel(_emailService.Object, _logger.Object, _userManager.Object);
}

[TestMethod]
public async Task OnPostAsync_WhenUserHasNotConfirmedEmail_RedirectsToCorrectPage()
{
    // Arrange
    _pageModel.Input = new ForgotPasswordPageModel() { Email = "[email protected]" };
    _userManager.Setup(x => x.FindByEmailAsync(It.IsAny<string>())).ReturnsAsync(new ApplicationUser());
    _userManager.Setup(x => x.IsEmailConfirmedAsync(It.IsAny<ApplicationUser>())).ReturnsAsync(false);

    // Act
    var result = await _pageModel.OnPostAsync();

    // Assert
    Assert.IsInstanceOfType(result, typeof(RedirectToPageResult));
    Assert.AreEqual("/Account/EmailNotConfirmed", result.PageName); //<-- Error Here
}

I'm trying to write an Assert statement to test that it redirects to the correct page. When I debug the unit test, I can see:

enter image description here

PageName = /Account/EmailNotConfirmed, but when I try to make an Assert statement from that, I get the following error:

'IActionResult' does not contain a definition for 'PageName' and no accessible extension method 'PageName' accepting a first argument of type 'IActionResult' could be found

What am I doing wrong?

Upvotes: 2

Views: 1371

Answers (1)

Nkosi
Nkosi

Reputation: 247123

You need to cast the result to the appropriate type to get access the desired members

//...

// Act
IActionResult result = await _pageModel.OnPostAsync();

// Assert
Assert.IsInstanceOfType(result, typeof(RedirectToPageResult));
RedirectToPageResult redirect = result as RedirectToPageResult; //<--cast here
Assert.AreEqual("/Account/EmailNotConfirmed", redirect.PageName);

Upvotes: 1

Related Questions