소스 정보
- 저장소
- runceel/ai-dev-dotnetapp
- 최근 소스 활동
- 2026년 4월 27일 08:47
- 감지된 SKILL.md 언어
- 일본어
- 스타
- 2
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
파일 탐색기
4 개 파일SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- bunit
- description
- bUnit 2.x を使用した Blazor コンポーネントのユニットテストのベストプラクティスとガイドライン
# bUnit 2.x — Blazor コンポーネントテストガイド
bUnit 2.x (現行最新 v2.7.x) を使った Blazor コンポーネントのユニットテスト作成を支援する。
テストコードは **C# (.cs) ファイル**で記述し、テストフレームワークには **MSTest** を使用する。
> **重要**: bUnit 2.x は **.NET 8 以上** を必須とする。
詳細なリファレンスは `references/` フォルダを参照 — 必要に応じてオンデマンドで読み込む。
| リファレンス | 内容 |
|---|---|
| [parameters.md](references/parameters.md) | パラメータ渡しの全パターン (EventCallback, ChildContent, Bind, Cascading 等) |
| [test-doubles.md](references/test-doubles.md) | JSInterop, NavigationManager, 認証, HttpClient, ComponentStub |
| [async-testing.md](references/async-testing.md) | WaitForAssertion, WaitForState, WaitForElement, TaskCompletionSource |
---
## 1. プロジェクトセットアップ
```xml
<Project Sdk="MSTest.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="bunit" Version="2.7.*" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyApp\MyApp.csproj" />
</ItemGroup>
</Project>
```
`global.json` には .NET 10 の Microsoft Testing Platform runner と `MSTest.Sdk` のバージョンを指定する。
```json
{
"test": {
"runner": "Microsoft.Testing.Platform"
},
"msbuild-sdks": {
"MSTest.Sdk": "4.2.1"
}
}
```
> テストプロジェクト内に `.razor` ファイルを置く特別な理由がない限り、SDK は `MSTest.Sdk` を使用すること。アプリ側の Razor コンポーネントは Web プロジェクトへの `ProjectReference` 経由でテストする。
---
## 2. テストの基本構造
### BunitContext を継承 (推奨)
```csharp
[TestClass]
public sealed class CounterTests : BunitContext
{
[TestMethod]
public void Counter_InitialRender_DisplaysZero()
{
// Act
var cut = Render<Counter>();
// Assert
cut.Find("p").MarkupMatches("<p>Current count: 0</p>");
}
}
```
### BunitContext を都度生成
```csharp
[TestMethod]
public void Counter_InitialRender_DisplaysZero()
{
using var ctx = new BunitContext();
var cut = ctx.Render<Counter>();
cut.MarkupMatches("<p>Current count: 0</p>");
}
```
---
## 3. コア API クイックリファレンス
### レンダリング
```csharp
var cut = Render<MyComponent>(); // パラメータなし
var cut = Render<MyComponent>(p => p.Add(x => x.Name, "test")); // パラメータ付き
cut.Render(p => p.Add(x => x.Name, "updated")); // 再レンダリング
```
### マークアップ検証
```csharp
cut.MarkupMatches("<p>Hello</p>"); // セマンティック HTML 比較
cut.Find("h1").MarkupMatches("<h1>Title</h1>"); // 要素単位
Assert.AreEqual("Hello", cut.Find("p").TextContent);
```
### 要素・コンポーネント検索
```csharp
var btn = cut.Find("button.primary"); // CSS セレクタ
var items = cut.FindAll("li"); // 複数 (自動更新なし)
var child = cut.FindComponent<TaskItem>(); // 子コンポーネント
var children = cut.FindComponents<TaskItem>(); // 複数
```
### イベント
```csharp
cut.Find("button").Click();
cut.Find("input").Change("new value");
cut.Find("form").Submit();
cut.Find("input").TriggerEvent("oncustompaste", new CustomPasteEventArgs { ... });
```
### 非同期待機
```csharp
cut.WaitForAssertion(() => cut.Find("p").MarkupMatches("<p>Done</p>"));
cut.WaitForState(() => cut.Instance.IsLoaded);
cut.WaitForElement("button.submit");
cut.WaitForElements("li", 3);
cut.WaitForComponent<ListItem>();
```
### サービス登録
```csharp
Services.AddSingleton<IMyService>(new MockMyService());
JSInterop.Mode = JSRuntimeMode.Loose; // JS 呼び出しを緩和
ComponentFactories.AddStub<HeavyChild>(); // 子コンポーネントをスタブ化
```
---
## 4. ベストプラクティス
### 構造
- テストクラスは `sealed` にする
- AAA パターン (Arrange-Act-Assert)
- テスト名: `ComponentName_Scenario_ExpectedBehavior`
- 変数名 `cut` を使用
### マークアップ検証
- 再利用コンポーネント → `MarkupMatches` で構造を検証
- アプリ固有コンポーネント → `Find` + `TextContent` / `Instance` でセマンティックに検証
- **不要な詳細を検証しない** — 脆いテストの原因になる
### 非同期
- `OnInitializedAsync` を持つコンポーネントには必ず `WaitForAssertion` / `WaitForState` を使用
- `TaskCompletionSource<T>` で非同期依存をシミュレート
### サービス・テストダブル
- テスト対象の依存は **必ず** `Services` に登録
- JSInterop は **デフォルトで Strict モード** — 必要な呼び出しは事前に `Setup` する
- 子コンポーネントの分離には `ComponentFactories.AddStub<T>()` を使用
### 避けるべきこと
- ❌ `FindAll` の結果を再利用せずに更新を期待する(再度 `FindAll` を呼ぶこと)
- ❌ JSInterop の `Setup` なしに JS 呼び出しを持つコンポーネントをレンダリング
GitHub에서 보기