How-To: Verify Blazor Navigation in bUnit

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");
    }
}
  1. We start with defining the route for this page: @page "/page-with-nav" (line #1).
  2. Then, we inject the NavigationManager class into our page (line #2). The @inject directive 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 called nav. NavigationManager is placed into the DI container by default by ASP.NET Core.
  3. First, we define a normal HTML hyperlink (line #6). When that link is clicked, the application navigates to page-1.
  4. Then, we define a button with an onclick event (line #7), which calls an event handler.
  5. Finally, the NavButtonClicked event handler(lines #10-13) uses the NavigationManager injected earlier to call its NavigateTo method. 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 RenderHyperlinks test (lines #12-27) performs the usual component rendering test (that we’ve done in many articles). And, we verify that the href for 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 ButtonLinkClicked test (lines #30-43) performs the navigation check on the button click.
    • After defining the TestContext, we get access to the NavigationManager from the context services. Notice that we didn’t have to place a test NavigationManager into the services. bUnit actually places its FakeNavigationManager into the services list.
    • This subclass of NavigationManager overrides the NavigateToCore method and only sets the new Uri property 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 Click action (this fires the button’s onclick event).
    • Finally, we assert that the NavigationManager.Uri property matches our expected destination URL.

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.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s