You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .github/copilot-instructions.md
+33-16Lines changed: 33 additions & 16 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -85,22 +85,39 @@ The SDK consists of three main packages:
85
85
- Test servers in `tests/ModelContextProtocol.Test*Server/` for integration scenarios
86
86
- Filter manual tests with `[Trait("Execution", "Manual")]` - these require external dependencies
87
87
88
-
### Test Infrastructure and Helpers
89
-
-**LoggedTest**: Base class for tests that need logging output captured to xUnit test output
90
-
- Provides `ILoggerFactory` and `ITestOutputHelper` for test logging
91
-
- Use when debugging or when tests need to verify log output
92
-
-**TestServerTransport**: In-memory transport for testing client-server interactions without network I/O
93
-
-**MockLoggerProvider**: For capturing and asserting on log messages
94
-
-**XunitLoggerProvider**: Routes `ILogger` output to xUnit's `ITestOutputHelper`
95
-
-**KestrelInMemoryTransport** (AspNetCore.Tests): In-memory Kestrel connection for HTTP transport testing without network stack
96
-
97
-
### Test Best Practices
98
-
- Inherit from `LoggedTest` for tests needing logging infrastructure
99
-
- Use `TestServerTransport` for in-memory client-server testing
100
-
- Mock external dependencies (filesystem, HTTP clients) rather than calling real services
101
-
- Use `CancellationTokenSource` with timeouts to prevent hanging tests
102
-
- Dispose resources properly (servers, clients, transports) using `IDisposable` or `await using`
103
-
- Run tests with: `dotnet test --filter '(Execution!=Manual)'`
88
+
### Test Base Classes
89
+
-**`LoggedTest`**: Base class that wires up `ILoggerFactory` with `XunitLoggerProvider` (test output) and `MockLoggerProvider` (log assertions). Inherit from this for any test needing logging.
90
+
-**`ClientServerTestBase`**: Sets up in-memory client/server pair via `Pipe`. Override `ConfigureServices` to register tools/prompts/resources, then call `CreateMcpClientForServer()`. Handles async disposal automatically.
91
+
-**`KestrelInMemoryTest`** (AspNetCore tests): Hosts ASP.NET Core with in-memory transport — no ports needed.
92
+
-**`TestServerTransport`**: In-memory mock transport for testing client logic without a real server.
93
+
94
+
### Transport Selection in Tests
95
+
-**Never use `WithStdioServerTransport()` in unit tests.** It reads from the test host's stdin, which cannot be closed, permanently leaking a thread pool thread per test.
96
+
- For DI-only tests: `WithStreamServerTransport(Stream.Null, Stream.Null)`
97
+
- For client/server interaction: inherit `ClientServerTestBase`
98
+
- For client-only logic: use `TestServerTransport`
99
+
- For HTTP/SSE: inherit `KestrelInMemoryTest`
100
+
- For process lifecycle tests: `StdioClientTransport` (only when testing actual process behavior)
101
+
102
+
### Resource Management
103
+
-**Always `await using` the `ServiceProvider`** when MCP server services are registered — `McpServerImpl` only implements `IAsyncDisposable`. Synchronous `using` throws at runtime.
104
+
-**Always dispose clients and servers** — use `await using var client = ...`
105
+
-**Use `TestContext.Current.CancellationToken`** for async MCP calls so xUnit can cancel on timeout.
106
+
107
+
### Timeouts
108
+
-**Always use `TestConstants.DefaultTimeout`** (60s) instead of hardcoded values. CI machines are slower than dev workstations.
109
+
- For HTTP polling operations use `TestConstants.HttpClientPollingTimeout` (2s).
110
+
111
+
### Synchronization
112
+
-**Never use `Task.Delay` for synchronization.** Use `TaskCompletionSource`, `SemaphoreSlim`, or `Channel` so tests don't depend on timing.
113
+
114
+
### Background Logging
115
+
-`ITestOutputHelper.WriteLine` throws after the test method returns. Background threads (process event handlers, async continuations) can outlive the test, causing unhandled exceptions that crash the test host.
- If calling `ITestOutputHelper` directly from an event handler, wrap in try/catch for `InvalidOperationException`.
118
+
119
+
### Parallelism
120
+
- Tests run in parallel by default. Apply `[Collection(nameof(DisableParallelization))]` to test classes that touch global state (e.g., `ActivitySource` listeners).
0 commit comments