Skip to content

Commit b6efae1

Browse files
ericstjCopilot
andcommitted
Fix flaky OutgoingFilter_MultipleFilters_ExecuteInOrder test
The outermost filter's 'after' callback runs after the response has been sent to the client via next(). In stateless/SSE mode, ListToolsAsync can return before the server-side filter pipeline finishes executing the 'after' callbacks. Assert.Equal then enumerates the executionOrder list concurrently with the filter adding to it, causing 'Collection was modified' InvalidOperationException. Fix by waiting for the outermost filter's 'after' callback to signal completion before asserting on the execution order. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 54caccc commit b6efae1

File tree

1 file changed

+7
-0
lines changed

1 file changed

+7
-0
lines changed

tests/ModelContextProtocol.AspNetCore.Tests/MapMcpTests.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ await client.CallToolAsync("sampling-tool",
394394
public async Task OutgoingFilter_MultipleFilters_ExecuteInOrder()
395395
{
396396
var executionOrder = new List<string>();
397+
var allFiltersComplete = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
397398

398399
Builder.Services.AddMcpServer()
399400
.WithHttpTransport(ConfigureStateless)
@@ -411,6 +412,7 @@ public async Task OutgoingFilter_MultipleFilters_ExecuteInOrder()
411412
if (context.JsonRpcMessage is JsonRpcResponse r2 && r2.Result is JsonObject obj2 && obj2.ContainsKey("tools"))
412413
{
413414
executionOrder.Add("filter1-after");
415+
allFiltersComplete.TrySetResult();
414416
}
415417
});
416418

@@ -439,6 +441,11 @@ public async Task OutgoingFilter_MultipleFilters_ExecuteInOrder()
439441

440442
await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
441443

444+
// The outermost filter's "after" callback runs after the response has been
445+
// sent to the client, so ListToolsAsync may return before it executes.
446+
// Wait for it to complete before asserting.
447+
await allFiltersComplete.Task.WaitAsync(TestContext.Current.CancellationToken);
448+
442449
Assert.Equal(["filter1-before", "filter2-before", "filter2-after", "filter1-after"], executionOrder);
443450
}
444451

0 commit comments

Comments
 (0)