CtrlK
BlogDocsLog inGet started
Tessl Logo

bunit-test-migration

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.

90

Quality

88%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

SKILL.md
Quality
Evals
Security

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
Repository
FritzAndFriends/BlazorWebFormsComponents
Last updated
Created

Is this your skill?

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.