FritzAndFriends / bunit-test-migration
Install for your project team
Run this command in your project directory to install the skill for your entire team:
mkdir -p .claude/skills/bunit-test-migration && curl -L -o skill.zip "https://fastmcp.me/Skills/Download/2856" && unzip -o skill.zip -d .claude/skills/bunit-test-migration && rm skill.zip
Project Skills
This skill will be saved in .claude/skills/bunit-test-migration/ and checked into git. All team members will have access to it automatically.
Important: Please verify the skill by reviewing its instructions before using it.
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.
0 views
0 installs
Skill Content
---
name: bunit-test-migration
description: 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.
---
# bUnit Test Migration Skill (Beta → 2.x)
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.
## When to Apply
Apply this skill when a `.razor` test file contains any of these patterns:
- `@inherits TestComponentBase`
- `<Fixture Test="...">`
- `<ComponentUnderTest>`
- `<SnapshotTest>`
- `void MethodName(Fixture fixture)`
## Transformation Rules
### 1. Change Inheritance
```diff
- @inherits TestComponentBase
+ @inherits BunitContext
```
### 2. Remove Wrapper Elements
Remove these XML elements entirely (keep only the component inside):
```diff
- <Fixture Test="TestName">
- <ComponentUnderTest>
<MyComponent Parameter="value" />
- </ComponentUnderTest>
- </Fixture>
```
### 3. Convert Test Methods
```diff
- void TestMethodName(Fixture fixture)
+ [Fact]
+ public void ComponentName_Scenario_ExpectedResult()
```
### 4. Replace Component Access
```diff
- var cut = fixture.GetComponentUnderTest();
+ var cut = Render(@<MyComponent Parameter="value" />);
```
### 5. Convert Snapshot Tests
```diff
- <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>);
+ }
```
## Complete Example
### Before
```razor
@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++;
}
```
### After
```razor
@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++;
}
```
## Test Naming Convention
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` |
## Special Patterns
### Multiple Tests in One File
Each `<Fixture>` block becomes a separate `[Fact]` method:
```razor
@inherits BunitContext
@code {
[Fact]
public void Component_FirstScenario_ExpectedResult() { ... }
[Fact]
public void Component_SecondScenario_ExpectedResult() { ... }
}
```
### Tests with Services
```razor
@code {
[Fact]
public void Component_WithService_Works()
{
Services.AddSingleton<IMyService>(new FakeService());
var cut = Render(@<MyComponent />);
}
}
```
### Authentication Tests
```razor
@code {
[Fact]
public void SecureComponent_AuthenticatedUser_ShowsContent()
{
var authContext = this.AddTestAuthorization();
authContext.SetAuthorized("TestUser");
authContext.SetRoles("Admin");
var cut = Render(@<SecureComponent />);
}
}
```
### Tests Requiring New TestContext
For tests that need isolated context (e.g., multiple renders):
```razor
@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");
}
}
```
### Tests with xUnit Logger (Optional)
For debugging complex tests, you can optionally enable xUnit logging:
```razor
@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.
## Quick Reference Table
| 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 />)` |
## Verification
After migrating a file, verify with:
```powershell
# 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"
```
## Common Errors
| 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 |