Page routing parameters allow developers to pass data to pages in their URL. bUnit allows us to pass routing parameters to pages, so that we can validate their behavior with test data. These parameters are set as part of the TestContext
rendering process. This works exactly the same way as testing component parameters.
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 with routing parameters in our project. If we don’t already have one, we can create one using the steps in the How-To: Define Routing Parameters on Blazor Page article.
Page with Routing Parameters
First, let’s review the HTML markup and code from the page with routing parameters article (called PageWithParameters
):
@page "/page-params/{Type}/{Id:int}"
@page "/page-params/{Type}"
<h3>Page With Parameter</h3>
<h5>Parameter Values:</h5>
<p>Type: @Type</p>
<p>Id: @Id</p>
@code {
[Parameter]
public string Type { get; set; }
[Parameter]
public int? Id { get; set; }
}
As we can see, we defined a couple of parameters on this page. And, we also defined a couple of routes using the @page
attribute which maps segments of the URL to those parameters. The Razor routing sets those entries in the URL fragment to the matching parameter names.
Create Test Class
Now, let’s create the PageWithParametersTests
class in the Blazor.HowTo.Tests project and Pages folder.
using Blazor.HowTo.Pages;
using Bunit;
using Xunit;
namespace Blazor.HowTo.Tests.Pages
{
public class PageWithParameterTests
{
[Fact]
public void InitialRender()
{
// arrange
var ctx = new TestContext();
// act
var comp = ctx.RenderComponent<PageWithParameter>();
// assert
var expectedHtml =
@" <h3>Page With Parameter</h3>
<h5>Parameter Values:</h5>
<p>Type:
</p>
<p>Id:
</p>
";
comp.MarkupMatches(expectedHtml);
}
[Fact]
public void InitialRender_WithParameters()
{
// arrange
var ctx = new TestContext();
// act
var comp = ctx.RenderComponent<PageWithParameter>(parameters => parameters
.Add(p => p.Type, "TestType")
.Add(p => p.Id, 1001));
// assert
var expectedHtml =
@" <h3>Page With Parameter</h3>
<h5>Parameter Values:</h5>
<p>Type: TestType
</p>
<p>Id: 1001
</p>
";
comp.MarkupMatches(expectedHtml);
}
[Fact]
public void InitialRender_WithoutOptionalId()
{
// arrange
var ctx = new TestContext();
// act
var comp = ctx.RenderComponent<PageWithParameter>(parameters => parameters
.Add(p => p.Type, "TestType"));
// assert
var expectedHtml =
@" <h3>Page With Parameter</h3>
<h5>Parameter Values:</h5>
<p>Type: TestType
</p>
<p>Id:
</p>
";
comp.MarkupMatches(expectedHtml);
}
}
}
The first test method (InitialRender
– lines #9-28) creates and renders the page without any parameters, so their default values are used… for strings, that’s null or empty string. So this first rendering is very simple, but verifies that our page will render even when no routing parameters are set.
In the InitialRender_WithParameters
test method (lines #30-51), we actually set both routing parameters and then render the page. Let’s see how that is done.
- We setup the bUnit
TestContext
as usual (line #34). - We call the
TestContext.RenderComponent
method for thePageWithParameter
type (line #37). But rather than using the empty argument overload of this method, we use the method that takes a list of component parameters. - I prefer to use the builder notation for adding parameters, so let’s define the
parameters
builder (also in line #37).- Add the
Type
parameter for our route (line #38). - Add the
Id
parameter for the route (line #39). - Notice that parameters builders use the Fluent API style, so we can chain
Add
calls for multiple parameters. - That’s all it takes… we have set all of our page routing parameters. And they will be used during the call to
TestContext.RenderComponent
.
- Add the
- Then, we define the expected rendered HTML (lines #43-49)… notice that we’ve added the parameter values to the output from the empty rendering.
- Finally, we use the
MarkupMatches
validation method to ensure that the page markup matches our expectations.
Finally, the InitialRender_WithoutOptionalId
test method (lines #53-73) verifies that our page rendering works correctly when the optional Id
parameter isn’t set. Since the Id
is an optional routing parameter, it is good to have a test for that condition. The structure of this test method matches the ones above.
We can follow these steps for any number and types of page routing parameters. The ability to simply pass parameters to a component under test is a powerful testability feature in bUnit.
Finally, let’s run the new tests in the Visual Studio TestExplorer and verify that they pass as we expect.
In conclusion, we can pass routing parameters to pages in the bUnit TestContext.RenderComponent
method. There are different ways to pass parameters to this method, but the parameter builder construct is the easiest to use. We can pass various different parameter values in separate tests, if we have rendering logic that is based on their values (or existence). So, this mechanism allows us to fully test the states of our pages.