Blazor components and pages can have normal HTML hyperlinks and navigation driven in code. Both forms allow users to move between pages. Blazor has the NavigationManager which allows our code to perform URL navigations. And, bUnit provides a mock NavigationManager to allow test code to request a navigation without actually performing it. Under our test context, our code can call NavigateTo and ensure the appropriate action was performed.
First, we must have a Blazor project and corresponding test project. Either open an existing solution or please follow the steps in the How-To: Add bUnit Test Project to Blazor Solution article to get both projects and all of the required packages. For this article, we called the projects: Blazor.HowTo and Blazor.HowTo.Tests.
Then, we need a Blazor page in our project. If we don’t already have one, we can create one using the steps in the How-To: Create New Page in Blazor article. For this article, we called the page: PageWithNavLinks.
Page with Navigation
First, let’s create a page with some navigations (the PageWithNavLinks.razor file):
@page "/page-with-nav"
@inject NavigationManager nav;
<h3>Page With NavLinks</h3>
<a id="normal-link" href="page-1">Normal Link</a>
<button id="button-link" @onclick="@NavButtonClicked">Button link</button>
@code {
private void NavButtonClicked()
{
nav.NavigateTo("page-2");
}
}
- We start with defining the route for this page:
@page "/page-with-nav"(line #1). - Then, we inject the
NavigationManagerclass into our page (line #2). The@injectdirective finds the specified type in the ASP.NET Core dependency injection system, then retrieves an instance of that type, and places it in a property callednav.NavigationManageris placed into the DI container by default by ASP.NET Core. - First, we define a normal HTML hyperlink (line #6). When that link is clicked, the application navigates to page-1.
- Then, we define a button with an
onclickevent (line #7), which calls an event handler. - Finally, the
NavButtonClickedevent handler(lines #10-13) uses theNavigationManagerinjected earlier to call itsNavigateTomethod. That operation navigates the application to page-2.
With this code in place, we now have a simple page with two methods of navigating to other pages.
Test Class
Now, let’s create the PageWithNavLinksTests class in the Blazor.HowTo.Tests project and Pages folder. In that test class we will implement a couple of tests:
using Blazor.HowTo.Pages;
using Bunit;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace Blazor.HowTo.Tests.Pages
{
public class PageWithNavLinksTests
{
[Fact]
public void RenderHyperlinks()
{
// arrange
var ctx = new TestContext();
// act
var cut = ctx.RenderComponent<PageWithNavLinks>();
// assert
var expectedMarkup =
@" <h3>Page With NavLinks</h3>
<a id=""normal-link"" href=""page-1"">Normal Link</a>
<button id=""button-link"">Button link</button>
";
cut.MarkupMatches(expectedMarkup);
}
[Fact]
public void ButtonLinkClicked()
{
// arrange
var ctx = new TestContext();
var nav = ctx.Services.GetRequiredService<NavigationManager>();
var cut = ctx.RenderComponent<PageWithNavLinks>();
// act
cut.Find("#button-link").Click();
// assert
Assert.Equal("http://localhost/page-2", nav.Uri);
}
}
}
- The
RenderHyperlinkstest (lines #12-27) performs the usual component rendering test (that we’ve done in many articles). And, we verify that thehreffor our page link is formatted as expected. Blazor is responsible for taking the hyperlink and navigating appropriately, so we don’t need any further validation of the navigation. - The
ButtonLinkClickedtest (lines #30-43) performs the navigation check on the button click.- After defining the
TestContext, we get access to theNavigationManagerfrom the context services. Notice that we didn’t have to place a testNavigationManagerinto the services. bUnit actually places itsFakeNavigationManagerinto the services list. - This subclass of
NavigationManageroverrides theNavigateToCoremethod and only sets the newUriproperty but doesn’t perform the actual navigation. - Then, we render the page.
- Next, we find the button on the page (using its id) and perform the
Clickaction (this fires the button’sonclickevent). - Finally, we assert that the
NavigationManager.Uriproperty matches our expected destination URL.
- After defining the
With both tests complete, we have covered both styles of navigation in our Blazor application. We have ensured that our click handling code is performing the navigation we expect.
Finally, let’s run the new tests in the Visual Studio TestExplorer and verify that they both pass as expected.
In conclusion, Blazor allows us to navigate between pages either using hyperlinks or the NavigationManager. We can verify hyperlinks are correct with bUnit rendering tests. We can test code that navigates via the NavigationManager by using the FakeNavigationManager defined in the bUnit library. With both mechanisms, we can verify that our pages/components will navigate as expected.
This test covers all that is needed for navigation to work properly, except for one thing: It does not test that page-2 has the proper @page directive.
This is somewhat unfortunate, because if we want to verify a multi-page use case, we cannot guarantee that, if the use case’s test passes, the application will work correctly. We’d still need something like Cypress.
LikeLike