Događaj
Power BI DataViz Svetsko prvenstvo
14. feb 16 - 31. mar 16
Sa 4 šanse za ulazak, možete osvojiti konferencijski paket i stići do LIVE Grand Finale u Las Vegasu
Saznajte višeOvaj pregledač više nije podržan.
Nadogradite na Microsoft Edge biste iskoristili najnovije funkcije, bezbednosne ispravke i tehničku podršku.
Napomena
This isn't the latest version of this article. For the current release, see the .NET 9 version of this article.
Upozorenje
This version of ASP.NET Core is no longer supported. For more information, see the .NET and .NET Core Support Policy. For the current release, see the .NET 9 version of this article.
Važno
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 9 version of this article.
By Egil Hansen
Testing Razor components is an important aspect of releasing stable and maintainable Blazor apps.
To test a Razor component, the component under test (CUT) is:
onclick
event for a button.Two common approaches for testing Razor components are end-to-end (E2E) testing and unit testing:
Unit testing: Unit tests are written with a unit testing library that provides:
bUnit is an example of a library that enables Razor component unit testing.
E2E testing: A test runner runs a Blazor app containing the CUT and automates a browser instance. The testing tool inspects and interacts with the CUT through the browser. Playwright for .NET is an example of an E2E testing framework that can be used with Blazor apps.
In unit testing, only the Razor component (Razor/C#) is involved. External dependencies, such as services and JS interop, must be mocked. In E2E testing, the Razor component and all of its auxiliary infrastructure are part of the test, including CSS, JS, and the DOM and browser APIs.
Test scope describes how extensive the tests are. Test scope typically has an influence on the speed of the tests. Unit tests run on a subset of the app's subsystems and usually execute in milliseconds. E2E tests, which test a broad group of the app's subsystems, can take several seconds to complete.
Unit testing also provides access to the instance of the CUT, allowing for inspection and verification of the component's internal state. This normally isn't possible in E2E testing.
With regard to the component's environment, E2E tests must make sure that the expected environmental state has been reached before verification starts. Otherwise, the result is unpredictable. In unit testing, the rendering of the CUT and the life cycle of the test are more integrated, which improves test stability.
E2E testing involves launching multiple processes, network and disk I/O, and other subsystem activity that often lead to poor test reliability. Unit tests are typically insulated from these sorts of issues.
The following table summarizes the difference between the two testing approaches.
Capability | Unit testing | E2E testing |
---|---|---|
Test scope | Razor component (Razor/C#) only | Razor component (Razor/C#) with CSS/JS |
Test execution time | Milliseconds | Seconds |
Access to the component instance | Yes | No |
Sensitive to the environment | No | Yes |
Reliability | More reliable | Less reliable |
Consider the scenario when choosing the type of testing to perform. Some considerations are described in the following table.
Scenario | Suggested approach | Remarks |
---|---|---|
Component without JS interop logic | Unit testing | When there's no dependency on JS interop in a Razor component, the component can be tested without access to JS or the DOM API. In this scenario, there are no disadvantages to choosing unit testing. |
Component with simple JS interop logic | Unit testing | It's common for components to query the DOM or trigger animations through JS interop. Unit testing is usually preferred in this scenario, since it's straightforward to mock the JS interaction through the IJSRuntime interface. |
Component that depends on complex JS code | Unit testing and separate JS testing | If a component uses JS interop to call a large or complex JS library but the interaction between the Razor component and JS library is simple, then the best approach is likely to treat the component and JS library or code as two separate parts and test each individually. Test the Razor component with a unit testing library, and test the JS with a JS testing library. |
Component with logic that depends on JS manipulation of the browser DOM | E2E testing | When a component's functionality is dependent on JS and its manipulation of the DOM, verify both the JS and Blazor code together in an E2E test. This is the approach that the Blazor framework developers have taken with Blazor's browser rendering logic, which has tightly-coupled C# and JS code. The C# and JS code must work together to correctly render Razor components in a browser. |
Component that depends on 3rd party class library with hard-to-mock dependencies | E2E testing | When a component's functionality is dependent on a 3rd party class library that has hard-to-mock dependencies, such as JS interop, E2E testing might be the only option to test the component. |
There's no official Microsoft testing framework for Blazor, but the community-driven project bUnit provides a convenient way to unit test Razor components.
Napomena
bUnit is a third-party testing library and isn't supported or maintained by Microsoft.
bUnit works with general-purpose testing frameworks, such as MSTest, NUnit, and xUnit. These testing frameworks make bUnit tests look and feel like regular unit tests. bUnit tests integrated with a general-purpose testing framework are ordinarily executed with:
dotnet test
CLI command in a command shell.Napomena
Test concepts and test implementations across different test frameworks are similar but not identical. Refer to the test framework's documentation for guidance.
The following demonstrates the structure of a bUnit test on the Counter
component in an app based on a Blazor project template. The Counter
component displays and increments a counter based on the user selecting a button in the page:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
The following bUnit test verifies that the CUT's counter is incremented correctly when the button is selected:
@code {
[Fact]
public void CounterShouldIncrementWhenClicked()
{
// Arrange
using var ctx = new TestContext();
var cut = ctx.Render(@<Counter />);
var paraElm = cut.Find("p");
// Act
cut.Find("button").Click();
// Assert
var paraElmText = paraElm.TextContent;
paraElm.MarkupMatches("Current count: 1");
}
}
Tests can also be written in a C# class file:
public class CounterTests
{
[Fact]
public void CounterShouldIncrementWhenClicked()
{
// Arrange
using var ctx = new TestContext();
var cut = ctx.RenderComponent<Counter>();
var paraElm = cut.Find("p");
// Act
cut.Find("button").Click();
// Assert
var paraElmText = paraElm.TextContent;
paraElmText.MarkupMatches("Current count: 1");
}
}
The following actions take place at each step of the test:
Arrange: The Counter
component is rendered using bUnit's TestContext
. The CUT's paragraph element (<p>
) is found and assigned to paraElm
. In Razor syntax, a component can be passed as a RenderFragment to bUnit.
Act: The button's element (<button>
) is located and selected by calling Click
, which should increment the counter and update the content of the paragraph tag (<p>
). The paragraph element text content is obtained by calling TextContent
.
Assert: MarkupMatches
is called on the text content to verify that it matches the expected string, which is Current count: 1
.
Napomena
The MarkupMatches
assert method differs from a regular string comparison assertion (for example, Assert.Equal("Current count: 1", paraElmText);
). MarkupMatches
performs a semantic comparison of the input and expected HTML markup. A semantic comparison is aware of HTML semantics, meaning things like insignificant whitespace is ignored. This results in more stable tests. For more information, see Customizing the Semantic HTML Comparison.
Povratne informacije za ASP.NET Core
ASP.NET Core je projekat otvorenog koda. Izaberite vezu da biste pružili povratne informacije:
Događaj
Power BI DataViz Svetsko prvenstvo
14. feb 16 - 31. mar 16
Sa 4 šanse za ulazak, možete osvojiti konferencijski paket i stići do LIVE Grand Finale u Las Vegasu
Saznajte višeObuka
Modul
C# testing in Visual Studio - Training
Start testing your C# apps by using the testing tools in Visual Studio. Learn to write tests, use Test Explorer, create test suites, and apply the red, green, refactor pattern to write code.