Search code examples
c#asp.net-corexunitxunit.net

Mock the Request when testing a Razor Page


I need to create a unit test for this function that resides inside the HomeModel razor page

public async Task<IActionResult> OnGetCurrencyAsync(string currency, CancellationToken ct = default)
{
    var returnUrl = Request.Headers["Referer"].ToString();
    var path = new System.Uri(returnUrl).LocalPath;

    if (string.IsNullOrWhiteSpace(path) || !Url.IsLocalUrl(path))
        returnUrl = Url.Content("~/");

    var session = await _currentUserService.GetOrInitializeSessionAsync(ct);
    if (!currency.IsNullOrEmpty())
    {
        session.Currency = currency;
        await _currentUserService.SetSession(session, ct);
    }

    return Redirect(returnUrl);
}

Till now I've created the following test

[Fact]
public async Task Test1()
{
    var returnUrl = "https://localhost:44317/paris";

    var currentuserService = new Mock<ICurrentUserService>();
    var options = new Mock<IOptions<Core.Configuration.AppSettings>>();
    var navigationMenu = new Mock<INavigationMenu>();
    var productModelService = new Mock<IProductModelService>();
    var userSavedProductRepository = new Mock<IUserSavedProductRepository>();
    var userSavedProductService = new Mock<IUserSavedProductService>();

    var homePage = new HomeModel(currentuserService.Object, options.Object, navigationMenu.Object, productModelService.Object, userSavedProductService.Object, userSavedProductRepository.Object);

    
    var res = await homePage.OnGetCurrencyAsync("EUR", CancellationToken.None);

    Assert.IsType<RedirectResult>(res);

    var redirectResult = (RedirectResult)res;

    Assert.True(returnUrl == redirectResult.Url);
}

But when I execute it, I got that .Request is null..

How can I correctly set it up?


Solution

  • The PageContext of the subject PageModel needs a HttpContext that contains the desired Request setup to satisfy the subject under test.

    Reference: Razor Pages unit tests in ASP.NET Core: Unit tests of the page model methods

    //Arrange
    var returnUrl = "https://localhost:44317/paris";
    
    
    //...code omitted for brevity
    
    
    // use a default context to have access to a request
    var httpContext = new DefaultHttpContext();
    httpContext.Request.Headers["Referer"] = returnUrl; //<--
    
    //these are needed as well for the page context
    var modelState = new ModelStateDictionary();
    var actionContext = new ActionContext(httpContext, new RouteData(), new PageActionDescriptor(), modelState);
    var modelMetadataProvider = new EmptyModelMetadataProvider();
    var viewData = new ViewDataDictionary(modelMetadataProvider, modelState);
    // need page context for the page model
    var pageContext = new PageContext(actionContext) {
        ViewData = viewData
    };
    
    //create model with necessary dependencies applied
    var homePage = new HomeModel(currentuserService.Object, options.Object, navigationMenu.Object, productModelService.Object, userSavedProductService.Object, userSavedProductRepository.Object) {
        PageContext = pageContext, //<--
        Url = new UrlHelper(actionContext)
    };
    
    //Act
    
    //...omitted for brevity