Component parameters allow developers to build interactive and reusable Blazor components. bUnit provides us a couple of mechanisms for passing parameters to components, so that we can validate their behavior with test data. These parameters are set as part of the TestContext
rendering process.
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 component in our project. If we don’t already have one, we can create one using the steps in the How-To: Define Parameters on Blazor Component article.
Component With Parameters
First, let’s review the component markup and code from the component parameters article:
<div class="col-12 pt-1 rounded border"
style="background-color: lightgray; cursor: pointer">
<img class="float-left mr-2 mt-2 align-items-center" src="@ImageLink" />
<h5><strong>@Title</strong></h5>
<p style="font-size: small">
@ChildContent
</p>
</div>
@code {
[Parameter]
public string Title { get; set; }
[Parameter]
public string ImageLink { get; set; }
[Parameter]
public RenderFragment ChildContent { get; set; }
}
As we can see, we defined 3 component parameters for parent components to set and which are data-bound into the component rendering.
Create Test Class
Now, let’s create the BannerAdTests
class in the Blazor.HowTo.Tests project and Components folder.
using Blazor.HowTo.Components;
using Bunit;
using Xunit;
namespace Blazor.HowTo.Tests.Components
{
public class BannerAdTests
{
[Fact]
public void InitialRender()
{
// arrange
var ctx = new TestContext();
// act
var comp = ctx.RenderComponent<BannerAd>();
// assert
var expectedHtml =
@" <div class=""col-12 pt-1 rounded border"" style=""background-color: lightgray; cursor: pointer"">
<img class=""float-left mr-2 mt-2 align-items-center"">
<h5>
<strong></strong>
</h5>
<p style=""font-size: small""></p>
</div>
";
comp.MarkupMatches(expectedHtml);
}
[Fact]
public void InitialRender_WithParameters()
{
// arrange
var ctx = new TestContext();
// act
var comp = ctx.RenderComponent<BannerAd>(parameters => parameters
.Add(p => p.Title, "Test Ad")
.Add(p => p.ImageLink, "/foo/test.png")
.AddChildContent("Test <strong>ad</strong> description.")
);
// assert
var expectedHtml =
@" <div class=""col-12 pt-1 rounded border""
style=""background-color: lightgray; cursor: pointer"">
<img class=""float-left mr-2 mt-2 align-items-center""
src=""/foo/test.png"">
<h5>
<strong>Test Ad</strong>
</h5>
<p style=""font-size: small"">Test <strong>ad</strong> description.</p>
</div>
";
comp.MarkupMatches(expectedHtml);
}
}
The first test method (InitialRender
– lines #9-20) creates and renders the component without any parameters, so their default values are used… for strings, that’s null or empty strings. So this first rendering is very simple with no image source, no title, and no description. But we have verified that our component will render even when no parameters are set.
In the InitialRender_WithParameters
test method (lines #31-57), we actually set the component parameters and then render it. Let’s see how that is done.
- We setup the bUnit
TestContext
as usual (line #35). - We call the
TestContext.RenderComponent
method for theBannerAd
type (line #38). But rather than using the empty parameter 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 we define the
parameters
builder (also in line #38).- Add the
Title
parameter for our component (line #39). - Add the
ImageLink
parameter for the component (line #40). - There is a separate method to add the
ChildContent
parameter to the component (line #41). And we are defining the child content with simple HTML markup to show that is possible to accept and render. - Notice that parameters uses the Fluent API style, so we can chain
Add
calls for multiple parameters. - That’s all it takes… we are set all of our component parameters. And they will be used during the call to
TestContext.RenderComponent
.
- Add the
- Then, we define the expected rendered HTML (lines #45-55)… 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 component markup matches our expectations.
We can follow these steps for any number and types of component parameters. This ability to simply pass parameters to a component under test is a powerful testability feature in bUnit.
Finally, let’s launch the new tests in the Visual Studio TestExplorer and verify that they pass as we expect.
In conclusion, we can pass component parameters to components 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 in our components.
One thought on “How-To: Write bUnit Tests for Components with Parameters”