Migrate bUnit test files from deprecated beta API (1.0.0-beta-10) to bUnit 2.x stable API. Use this when working on .razor test files in BlazorWebFormsComponents.Test that contain old patterns like TestComponentBase, Fixture, or SnapshotTest.
72
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This skill provides guidance for migrating test files from the deprecated bUnit 1.0.0-beta-10 API to bUnit 2.5.3 stable API. Use this when you encounter test files using the old TestComponentBase, <Fixture>, or <SnapshotTest> patterns.
Apply this skill when a .razor test file contains any of these patterns:
@inherits TestComponentBase<Fixture Test="..."><ComponentUnderTest><SnapshotTest>void MethodName(Fixture fixture)- @inherits TestComponentBase
+ @inherits BunitContextRemove these XML elements entirely (keep only the component inside):
- <Fixture Test="TestName">
- <ComponentUnderTest>
<MyComponent Parameter="value" />
- </ComponentUnderTest>
- </Fixture>- void TestMethodName(Fixture fixture)
+ [Fact]
+ public void ComponentName_Scenario_ExpectedResult()- var cut = fixture.GetComponentUnderTest();
+ var cut = Render(@<MyComponent Parameter="value" />);- <SnapshotTest Description="renders correctly">
- <TestInput>
- <MyComponent />
- </TestInput>
- <ExpectedOutput>
- <div>expected html</div>
- </ExpectedOutput>
- </SnapshotTest>
+ [Fact]
+ public void MyComponent_Default_RendersCorrectly()
+ {
+ var cut = Render(@<MyComponent />);
+ cut.MarkupMatches(@<div>expected html</div>);
+ }@inherits TestComponentBase
<Fixture Test="ShouldClickButton">
<ComponentUnderTest>
<Button OnClick="OnClick">Click me</Button>
</ComponentUnderTest>
</Fixture>
@code {
int ClickCount = 0;
void ShouldClickButton(Fixture fixture)
{
var cut = fixture.GetComponentUnderTest();
cut.Find("button").Click();
ClickCount.ShouldBe(1);
}
void OnClick() => ClickCount++;
}@inherits BunitContext
@code {
int ClickCount = 0;
[Fact]
public void Button_Click_IncrementsCounter()
{
var cut = Render(@<Button OnClick="OnClick">Click me</Button>);
cut.Find("button").Click();
ClickCount.ShouldBe(1);
}
void OnClick() => ClickCount++;
}Pattern: ComponentName_Scenario_ExpectedResult
| Component | Scenario | Result | Test Name |
|---|---|---|---|
| Button | Click | InvokesHandler | Button_Click_InvokesHandler |
| DataList | EmptySource | ShowsEmptyTemplate | DataList_EmptySource_ShowsEmptyTemplate |
| GridView | WithData | RendersRows | GridView_WithData_RendersRows |
Each <Fixture> block becomes a separate [Fact] method:
@inherits BunitContext
@code {
[Fact]
public void Component_FirstScenario_ExpectedResult() { ... }
[Fact]
public void Component_SecondScenario_ExpectedResult() { ... }
}@code {
[Fact]
public void Component_WithService_Works()
{
Services.AddSingleton<IMyService>(new FakeService());
var cut = Render(@<MyComponent />);
}
}@code {
[Fact]
public void SecureComponent_AuthenticatedUser_ShowsContent()
{
var authContext = this.AddTestAuthorization();
authContext.SetAuthorized("TestUser");
authContext.SetRoles("Admin");
var cut = Render(@<SecureComponent />);
}
}For tests that need isolated context (e.g., multiple renders):
@code {
[Fact]
public void Component_MultipleRenders_WorksCorrectly()
{
using var ctx = new Bunit.TestContext();
var cut1 = ctx.Render(@<MyComponent Value="1" />);
var cut2 = ctx.Render(@<MyComponent Value="2" />);
cut1.Find("span").TextContent.ShouldBe("1");
cut2.Find("span").TextContent.ShouldBe("2");
}
}For debugging complex tests, you can optionally enable xUnit logging:
@using Microsoft.Extensions.Logging
@code {
private ILogger<MyTest> _logger;
public MyTest(ITestOutputHelper output) : base(output)
{
}
[Fact]
public void Component_ComplexScenario_WorksAsExpected()
{
_logger = Services.GetService<ILogger<MyTest>>();
_logger?.LogInformation("Starting test");
var cut = Render(@<MyComponent />);
_logger?.LogDebug("Component rendered");
// Test assertions...
}
}Note: Only add logging when diagnostic output is helpful. Most tests should remain simple without logging.
| Old Pattern | New Pattern |
|---|---|
@inherits TestComponentBase | @inherits BunitContext |
<Fixture Test="Name"> | Remove |
<ComponentUnderTest> | Remove |
<SnapshotTest> | [Fact] method with MarkupMatches() |
void Name(Fixture fixture) | [Fact] public void Name() |
fixture.GetComponentUnderTest() | Render(@<Component />) |
fixture.GetComponentUnderTest<T>() | Render<T>(@<Component />) |
After migrating a file, verify with:
# Build check
dotnet build src/BlazorWebFormsComponents.Test --no-restore
# List discovered tests
dotnet test src/BlazorWebFormsComponents.Test --list-tests --filter "FullyQualifiedName~ComponentName"
# Run tests
dotnet test src/BlazorWebFormsComponents.Test --filter "FullyQualifiedName~ComponentName"| Error | Cause | Fix |
|---|---|---|
CS0246: TestComponentBase not found | Old inheritance | Change to @inherits BunitContext |
CS0103: Fixture does not exist | Old wrapper element | Remove <Fixture> tags |
No tests discovered | Missing [Fact] attribute | Add [Fact] to test methods |
Method must be public | Private test method | Add public modifier |
2072069
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.