Create ChatAgent.Api.Tests and ChatAgent.Client.Tests projects with xUnit and Moq. Test HealthController (200 + valid response), ChatController (SSE streaming with mocked upstream, error handling), and ChatApiClient (delta parsing, error events, health endpoint). 6 tests, all passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.0 KiB
Context
No test projects exist. The solution has 3 projects (Client, Api, Shared) under src/. Tests need to cover the API controllers and the client's ChatApiClient service, both of which involve HTTP and SSE streaming.
Goals / Non-Goals
Goals:
- Establish test infrastructure (xUnit + Moq)
- Test API controllers using WebApplicationFactory (integration-style)
- Test ChatApiClient using a mock HttpMessageHandler (unit-style)
- All tests runnable via
dotnet testfrom solution root
Non-Goals:
- Blazor component tests (bUnit) — Chat.razor is UI-heavy, defer to a future phase
- End-to-end browser tests (Playwright/Selenium)
- Testing the upstream Responses API itself
Decisions
Decision 1: Test framework — xUnit + Moq
xUnit is the .NET standard. Moq for mocking HttpMessageHandler so we can control HTTP responses in tests without hitting real servers.
Decision 2: Test project layout
tests/
├── ChatAgent.Api.Tests/ → references Api project
└── ChatAgent.Client.Tests/ → references Client project + Shared
Both added to the ChatAgent.sln solution file under a tests solution folder.
Decision 3: API tests use WebApplicationFactory
Microsoft.AspNetCore.Mvc.Testing provides WebApplicationFactory<Program> for integration-style tests. For ChatController, we inject a mock IHttpClientFactory that returns a handler with canned SSE responses — no real Responses API needed.
Decision 4: Client tests mock HttpMessageHandler
ChatApiClient takes an HttpClient. Tests create an HttpClient with a custom DelegatingHandler that returns canned SSE response streams. This tests the SSE parsing logic in isolation.
Risks / Trade-offs
- [WebApplicationFactory requires Api's Program to be accessible] → Add
InternalsVisibleToor use thepublic partial class Program {}trick in Api's Program.cs - [SSE stream mocking is verbose] → Create a small helper method that builds SSE response content from a list of events