SparkyTestHelpers: ASP.NET MVC Core Razor Pages

part of the “SparkyTestHelpers” suite of .NET unit testing tools

photo by RaSeBo

NuGet package | Source code

I knew that “Razor Pages” were a new option in ASP.NET MVC Core, but didn’t have a good understanding of their use until I learned about them via Scott Allen’s excellent “ASP.NET Core Fundamentals” Pluralsight course.

I was vaguely aware that they were a simpler alternative to “traditional” MVC, but when I hear Microsoft talking about making things “easier and more productive”, I fear that it’s going to be some godawful LightSwitch-y debacle.

Good news: It’s not a debacle. It’s a well-designed, lightweight (yet still powerful) alternative to Controllers that should be useful in many scenarios, and it’s testable.

…But why not make testing even easier?

Last week, I blogged about testing MVC Controller Actions with the SparkyTestHelpers.AspNetMvc.Core NuGet package. Today I added helpers for Razor Page testing:

PageModelTester<TPageModel>

ASP.NET MVC Razor Page PageModels have a lot in common with Controllers (they kind of combine the “C” and “M” of MVC), so the tester classes are pretty similar to ControllerTester and ControllerActionTester

PageModelTester Instantiation:

using SparkyTestHelpers.AspNetMvc
var homeModel = new HomeModel(/* with test dependencies */);
var pageTester = new PageModelTester<HomeModel>(homeModel);

It doesn’t do anything on its own — just provides an Action(actionDefinitionExpression) method that’s used to create a…

PageModelActionTester<TPageModel>

var actionTester = 
new PageModelTester<HomeModel>(homeModel).Action(x => x.OnGet);

PageModelActionTester has several .Test… methods used to assert that the PageModel action returns the expected IActionResult implementation. There are methods for many standard result types, plus the generic TestResult<TActionResultType> method:

  • .TestContent((optional) Action<ContentResult> validate)
  • .TestFile((optional) Action<FileResult> validate)
  • .TestJsonResult((optional) Action<JsonResult> validate)
  • .TestPage((optional) Action<PageResult> validate)
  • .TestRedirectToAction(string expecteActionName, string expectedControllerName, object expectedRouteValues, (optional) Action<RedirectToRouteResult> validate)
  • .TestRedirectToPage(string expectedPageName, (optional) Action<RedirectToPageResult> validate)
  • .TestRedirectToRoute(string expectedRoute, (optional) Action<RedirectToRouteResult> validate)
  • .TestResult<TActionResultType>((optional) Action<TActionResultType> validate)

Additional methods:

  • .ExpectingModel<TModelType>((optional) Action<TModelType> validate) — used with .TestJson. Can also be used with .TestPage, but it’s more efficient to use…
  • .ExpectingModel(Action<TPageModel> validate) — used with .TestPage to perform validation PageModel property validation
  • WhenModelStateIsValidEquals(bool isValid) — used to test conditional logic based on ModelState.IsValid

The validate “callback” methods may be used for additional data assertions, beyond testing proper return types.

Examples:

var homeModel = new HomeModel(/* with test dependencies */);
var pageTester = new PageModelTester<HomeModel>(homeModel);
pageTester
.Action(x => x.OnGet)
.ExpectingModel(model => Assert.IsTrue(model.Foo))
.TestPage();
pageTester
.Action(x => x.OnPost)
.WhenModelStateIsValidEquals(false)
.ExpectingModel(model =>
Assert.AreEqual(expectedErrorMessage, model.ErrorMessage))
.TestPage();
pageTester
.Action(x => x.Post)
.WhenModelStateIsValidEquals(true)
.TestRedirectToPage("UpdateSuccessful");

Happy Testing!