BU

bunit-test-migration

Updates legacy bUnit test code to the 2.x stable API. Fixes deprecated test patterns in Blazor component tests.

Install

mkdir -p .claude/skills/bunit-test-migration && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2856" && unzip -o skill.zip -d .claude/skills/bunit-test-migration && rm skill.zip

Installs to .claude/skills/bunit-test-migration

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

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.
242 chars✓ has a “when” trigger
Beginner

Key capabilities

  • Migrate test inheritance to BunitContext
  • Convert legacy Fixture patterns to [Fact] methods
  • Replace SnapshotTest with MarkupMatches
  • Update component rendering syntax

How it works

The skill applies transformation rules to replace deprecated bUnit beta components and methods with modern 2.x stable API equivalents.

Inputs & outputs

You give it
Legacy .razor test file
You get back
Migrated .razor test file

When to use bunit-test-migration

  • Upgrade bUnit tests to 2.x
  • Replace TestComponentBase with BunitContext
  • Convert SnapshotTest patterns to [Fact] tests
  • Clean up legacy component testing code

About this skill

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

- @inherits TestComponentBase
+ @inherits BunitContext

2. Remove Wrapper Elements

Remove these XML elements entirely (keep only the component inside):

- <Fixture Test="TestName">
-     <ComponentUnderTest>
          <MyComponent Parameter="value" />
-     </ComponentUnderTest>
- </Fixture>

3. Convert Test Methods

- void TestMethodName(Fixture fixture)
+ [Fact]
+ public void ComponentName_Scenario_ExpectedResult()

4. Replace Component Access

- var cut = fixture.GetComponentUnderTest();
+ var cut = Render(@<MyComponent Parameter="value" />);

5. Convert Snapshot Tests

- <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

@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

@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

ComponentScenarioResultTest Name
ButtonClickInvokesHandlerButton_Click_InvokesHandler
DataListEmptySourceShowsEmptyTemplateDataList_EmptySource_ShowsEmptyTemplate
GridViewWithDataRendersRowsGridView_WithData_RendersRows

Special Patterns

Multiple Tests in One File

Each <Fixture> block becomes a separate [Fact] method:

@inherits BunitContext

@code {
    [Fact]
    public void Component_FirstScenario_ExpectedResult() { ... }

    [Fact]
    public void Component_SecondScenario_ExpectedResult() { ... }
}

Tests with Services

@code {
    [Fact]
    public void Component_WithService_Works()
    {
        Services.AddSingleton<IMyService>(new FakeService());

        var cut = Render(@<MyComponent />);
    }
}

Authentication Tests

@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):

@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:

@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 PatternNew 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:

# 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

ErrorCauseFix
CS0246: TestComponentBase not foundOld inheritanceChange to @inherits BunitContext
CS0103: Fixture does not existOld wrapper elementRemove <Fixture> tags
No tests discoveredMissing [Fact] attributeAdd [Fact] to test methods
Method must be publicPrivate test methodAdd public modifier

When not to use it

  • For non-bUnit test files
  • When working with bUnit 1.x projects that cannot be upgraded

Prerequisites

bUnit 2.x environmentExisting test files using beta patterns

Limitations

  • Only supports migration from 1.0.0-beta-10
  • Requires manual verification of test logic

How it compares

It automates the refactoring of obsolete test patterns, which would otherwise require manual, error-prone code updates.

Compared to similar skills

bunit-test-migration side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
bunit-test-migration (this skill)16moNo flagsBeginner
csharp-pro94moNo flagsIntermediate
performance-benchmark34moNo flagsIntermediate
run-device-tests32moReviewAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

Search skills

Search the agent skills registry