Skip to content

Commit 7e7949e

Browse files
committed
Upgrade to xunit.v3
1 parent fd358b4 commit 7e7949e

11 files changed

+91
-115
lines changed

Directory.Packages.props

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<PackageVersion Include="Serilog.Sinks.Debug" Version="3.0.0" />
3636
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
3737
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="$(System10Version)" />
38-
<PackageVersion Include="xunit" Version="2.9.2" />
39-
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.0" />
38+
<PackageVersion Include="xunit.v3" Version="2.0.0" />
39+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
4040
</ItemGroup>
4141
</Project>

tests/ModelContextProtocol.TestServer/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Text;
2-
using System.Text.Json;
32
using ModelContextProtocol.Protocol.Messages;
43
using ModelContextProtocol.Protocol.Transport;
54
using ModelContextProtocol.Protocol.Types;

tests/ModelContextProtocol.Tests/Client/McpClientFactoryTests.cs

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,28 @@ public class McpClientFactoryTests
1717
[Fact]
1818
public async Task CreateAsync_WithInvalidArgs_Throws()
1919
{
20-
await Assert.ThrowsAsync<ArgumentNullException>("serverConfig", () => McpClientFactory.CreateAsync((McpServerConfig)null!, _defaultOptions));
20+
await Assert.ThrowsAsync<ArgumentNullException>("serverConfig", () => McpClientFactory.CreateAsync((McpServerConfig)null!, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
2121

22-
await Assert.ThrowsAsync<ArgumentNullException>("clientOptions", () => McpClientFactory.CreateAsync(
23-
new McpServerConfig()
22+
await Assert.ThrowsAsync<ArgumentNullException>("clientOptions", () => McpClientFactory.CreateAsync(new McpServerConfig()
2423
{
2524
Name = "name",
2625
Id = "id",
2726
TransportType = TransportTypes.StdIo,
28-
}, (McpClientOptions)null!));
27+
}, (McpClientOptions)null!, cancellationToken: TestContext.Current.CancellationToken));
2928

30-
await Assert.ThrowsAsync<ArgumentException>("serverConfig", () => McpClientFactory.CreateAsync(
31-
new McpServerConfig()
29+
await Assert.ThrowsAsync<ArgumentException>("serverConfig", () => McpClientFactory.CreateAsync(new McpServerConfig()
3230
{
3331
Name = "name",
3432
Id = "id",
3533
TransportType = "somethingunsupported",
36-
},
37-
_defaultOptions));
34+
}, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
3835

39-
await Assert.ThrowsAsync<InvalidOperationException>(() => McpClientFactory.CreateAsync(
40-
new McpServerConfig()
36+
await Assert.ThrowsAsync<InvalidOperationException>(() => McpClientFactory.CreateAsync(new McpServerConfig()
4137
{
4238
Name = "name",
4339
Id = "id",
4440
TransportType = TransportTypes.StdIo,
45-
},
46-
_defaultOptions,
47-
(_, __) => null!));
41+
}, _defaultOptions, (_, __) => null!, cancellationToken: TestContext.Current.CancellationToken));
4842
}
4943

5044
[Fact]
@@ -65,10 +59,7 @@ public async Task CreateAsync_WithValidStdioConfig_CreatesNewClient()
6559
};
6660

6761
// Act
68-
var client = await McpClientFactory.CreateAsync(
69-
serverConfig,
70-
_defaultOptions,
71-
(_, __) => new NopTransport());
62+
await using var client = await McpClientFactory.CreateAsync(serverConfig, _defaultOptions, (_, __) => new NopTransport(), cancellationToken: TestContext.Current.CancellationToken);
7263

7364
// Assert
7465
Assert.NotNull(client);
@@ -88,10 +79,7 @@ public async Task CreateAsync_WithNoTransportOptions_CreatesNewClient()
8879
};
8980

9081
// Act
91-
var client = await McpClientFactory.CreateAsync(
92-
serverConfig,
93-
_defaultOptions,
94-
(_, __) => new NopTransport());
82+
await using var client = await McpClientFactory.CreateAsync(serverConfig, _defaultOptions, (_, __) => new NopTransport(), cancellationToken: TestContext.Current.CancellationToken);
9583

9684
// Assert
9785
Assert.NotNull(client);
@@ -111,10 +99,7 @@ public async Task CreateAsync_WithValidSseConfig_CreatesNewClient()
11199
};
112100

113101
// Act
114-
var client = await McpClientFactory.CreateAsync(
115-
serverConfig,
116-
_defaultOptions,
117-
(_, __) => new NopTransport());
102+
await using var client = await McpClientFactory.CreateAsync(serverConfig, _defaultOptions, (_, __) => new NopTransport(), cancellationToken: TestContext.Current.CancellationToken);
118103

119104
// Assert
120105
Assert.NotNull(client);
@@ -141,10 +126,7 @@ public async Task CreateAsync_WithSse_CreatesCorrectTransportOptions()
141126
};
142127

143128
// Act
144-
var client = await McpClientFactory.CreateAsync(
145-
serverConfig,
146-
_defaultOptions,
147-
(_, __) => new NopTransport());
129+
await using var client = await McpClientFactory.CreateAsync(serverConfig, _defaultOptions, (_, __) => new NopTransport(), cancellationToken: TestContext.Current.CancellationToken);
148130

149131
// Assert
150132
Assert.NotNull(client);
@@ -171,7 +153,7 @@ public async Task McpFactory_WithInvalidTransportOptions_ThrowsFormatException(s
171153
};
172154

173155
// act & assert
174-
await Assert.ThrowsAsync<ArgumentException>(() => McpClientFactory.CreateAsync(config, _defaultOptions));
156+
await Assert.ThrowsAsync<ArgumentException>(() => McpClientFactory.CreateAsync(config, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
175157
}
176158

177159
private sealed class NopTransport : IClientTransport

tests/ModelContextProtocol.Tests/ClientIntegrationTests.cs

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using ModelContextProtocol.Client;
2-
using ModelContextProtocol.Configuration;
3-
using ModelContextProtocol.Protocol.Messages;
4-
using ModelContextProtocol.Protocol.Transport;
5-
using ModelContextProtocol.Protocol.Types;
62
using Microsoft.Extensions.AI;
73
using OpenAI;
4+
using ModelContextProtocol.Protocol.Types;
5+
using ModelContextProtocol.Protocol.Messages;
86
using System.Text.Json;
7+
using ModelContextProtocol.Configuration;
8+
using ModelContextProtocol.Protocol.Transport;
9+
using Xunit.Sdk;
910

1011
namespace ModelContextProtocol.Tests;
1112

@@ -61,8 +62,8 @@ public async Task ListTools_Stdio(string clientId)
6162

6263
// act
6364
await using var client = await _fixture.CreateClientAsync(clientId);
64-
var tools = await client.ListToolsAsync().ToListAsync();
65-
var aiFunctions = await client.GetAIFunctionsAsync();
65+
var tools = await client.ListToolsAsync(TestContext.Current.CancellationToken).ToListAsync(TestContext.Current.CancellationToken);
66+
var aiFunctions = await client.GetAIFunctionsAsync(TestContext.Current.CancellationToken);
6667

6768
// assert
6869
Assert.NotEmpty(tools);
@@ -102,9 +103,9 @@ public async Task CallTool_Stdio_ViaAIFunction_EchoServer(string clientId)
102103

103104
// act
104105
await using var client = await _fixture.CreateClientAsync(clientId);
105-
var aiFunctions = await client.GetAIFunctionsAsync();
106+
var aiFunctions = await client.GetAIFunctionsAsync(TestContext.Current.CancellationToken);
106107
var echo = aiFunctions.Single(t => t.Name == "echo");
107-
var result = await echo.InvokeAsync([new KeyValuePair<string, object?>("message", "Hello MCP!")]);
108+
var result = await echo.InvokeAsync([new KeyValuePair<string, object?>("message", "Hello MCP!")], TestContext.Current.CancellationToken);
108109

109110
// assert
110111
Assert.NotNull(result);
@@ -119,7 +120,7 @@ public async Task ListPrompts_Stdio(string clientId)
119120

120121
// act
121122
await using var client = await _fixture.CreateClientAsync(clientId);
122-
var prompts = await client.ListPromptsAsync().ToListAsync();
123+
var prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken).ToListAsync(TestContext.Current.CancellationToken);
123124

124125
// assert
125126
Assert.NotEmpty(prompts);
@@ -251,7 +252,7 @@ public async Task SubscribeResource_Stdio()
251252
await client.SubscribeToResourceAsync("test://static/resource/1", CancellationToken.None);
252253

253254
// notifications happen every 5 seconds, so we wait for 10 seconds to ensure we get at least one notification
254-
await Task.Delay(10000);
255+
await Task.Delay(10000, TestContext.Current.CancellationToken);
255256

256257
// assert
257258
Assert.True(counter > 0);
@@ -276,17 +277,17 @@ public async Task UnsubscribeResource_Stdio()
276277
await client.SubscribeToResourceAsync("test://static/resource/1", CancellationToken.None);
277278

278279
// notifications happen every 5 seconds, so we wait for 10 seconds to ensure we get at least one notification
279-
await Task.Delay(10000);
280+
await Task.Delay(10000, TestContext.Current.CancellationToken);
280281

281282
// reset counter
282283
int counterAfterSubscribe = counter;
283-
284+
284285
// unsubscribe
285286
await client.UnsubscribeFromResourceAsync("test://static/resource/1", CancellationToken.None);
286287
counter = 0;
287288

288289
// notifications happen every 5 seconds, so we wait for 10 seconds to ensure we would've gotten at least one notification
289-
await Task.Delay(10000);
290+
await Task.Delay(10000, TestContext.Current.CancellationToken);
290291

291292
// assert
292293
Assert.True(counterAfterSubscribe > 0);
@@ -340,7 +341,7 @@ public async Task GetCompletion_Stdio_PromptReference(string clientId)
340341
[Theory]
341342
[MemberData(nameof(GetClients))]
342343
public async Task Sampling_Stdio(string clientId)
343-
{
344+
{
344345
// Set up the sampling handler
345346
int samplingHandlerCalls = 0;
346347
await using var client = await _fixture.CreateClientAsync(clientId, new()
@@ -375,8 +376,8 @@ public async Task Sampling_Stdio(string clientId)
375376
{
376377
["prompt"] = "Test prompt",
377378
["maxTokens"] = 100
378-
}
379-
);
379+
},
380+
TestContext.Current.CancellationToken);
380381

381382
// assert
382383
Assert.NotNull(result);
@@ -423,8 +424,8 @@ public async Task Notifications_Stdio(string clientId)
423424
await using var client = await _fixture.CreateClientAsync(clientId);
424425

425426
// Verify we can send notifications without errors
426-
await client.SendNotificationAsync(NotificationMethods.RootsUpdatedNotification);
427-
await client.SendNotificationAsync("test/notification", new { test = true });
427+
await client.SendNotificationAsync(NotificationMethods.RootsUpdatedNotification, cancellationToken: TestContext.Current.CancellationToken);
428+
await client.SendNotificationAsync("test/notification", new { test = true }, TestContext.Current.CancellationToken);
428429

429430
// assert
430431
// no response to check, if no exception is thrown, it's a success
@@ -452,13 +453,13 @@ public async Task CallTool_Stdio_MemoryServer()
452453
ClientInfo = new() { Name = "IntegrationTestClient", Version = "1.0.0" }
453454
};
454455

455-
await using var client = await McpClientFactory.CreateAsync(serverConfig, clientOptions, loggerFactory: _fixture.LoggerFactory);
456+
await using var client = await McpClientFactory.CreateAsync(serverConfig, clientOptions, loggerFactory: _fixture.LoggerFactory, cancellationToken: TestContext.Current.CancellationToken);
456457

457458
// act
458459
var result = await client.CallToolAsync(
459460
"read_graph",
460-
[]
461-
);
461+
[],
462+
TestContext.Current.CancellationToken);
462463

463464
// assert
464465
Assert.NotNull(result);
@@ -471,14 +472,11 @@ public async Task CallTool_Stdio_MemoryServer()
471472
[Fact]
472473
public async Task GetAIFunctionsAsync_UsingEverythingServer_ToolsAreProperlyCalled()
473474
{
474-
if (s_openAIKey is null)
475-
{
476-
return; // Skip the test if the OpenAI key is not provided
477-
}
475+
SkipTestIfNoOpenAIKey();
478476

479477
// Get the MCP client and tools from it.
480-
await using var client = await McpClientFactory.CreateAsync(_fixture.EverythingServerConfig, _fixture.DefaultOptions); ;
481-
var mappedTools = await client.GetAIFunctionsAsync();
478+
await using var client = await McpClientFactory.CreateAsync(_fixture.EverythingServerConfig, _fixture.DefaultOptions, cancellationToken: TestContext.Current.CancellationToken);
479+
var mappedTools = await client.GetAIFunctionsAsync(TestContext.Current.CancellationToken);
482480

483481
// Create the chat client.
484482
using IChatClient chatClient = new OpenAIClient(s_openAIKey).AsChatClient("gpt-4o-mini")
@@ -495,7 +493,7 @@ public async Task GetAIFunctionsAsync_UsingEverythingServer_ToolsAreProperlyCall
495493
messages.Add(new(ChatRole.User, "Please call the echo tool with the string 'Hello MCP!' and output the response ad verbatim."));
496494

497495
// Call the chat client
498-
var response = await chatClient.GetResponseAsync(messages, new() { Tools = [.. mappedTools], Temperature = 0 });
496+
var response = await chatClient.GetResponseAsync(messages, new() { Tools = [.. mappedTools], Temperature = 0 }, TestContext.Current.CancellationToken);
499497

500498
// Assert
501499
Assert.Contains("Echo: Hello MCP!", response.Text);
@@ -504,10 +502,7 @@ public async Task GetAIFunctionsAsync_UsingEverythingServer_ToolsAreProperlyCall
504502
[Fact]
505503
public async Task SamplingViaChatClient_RequestResponseProperlyPropagated()
506504
{
507-
if (s_openAIKey is null)
508-
{
509-
return; // Skip the test if the OpenAI key is not provided
510-
}
505+
SkipTestIfNoOpenAIKey();
511506

512507
await using var client = await McpClientFactory.CreateAsync(_fixture.EverythingServerConfig, new()
513508
{
@@ -519,17 +514,25 @@ public async Task SamplingViaChatClient_RequestResponseProperlyPropagated()
519514
SamplingHandler = new OpenAIClient(s_openAIKey).AsChatClient("gpt-4o-mini").CreateSamplingHandler(),
520515
},
521516
},
522-
});
517+
}, cancellationToken: TestContext.Current.CancellationToken);
523518

524519
var result = await client.CallToolAsync("sampleLLM", new()
525520
{
526521
["prompt"] = "In just a few words, what is the most famous tower in Paris?",
527-
});
522+
}, TestContext.Current.CancellationToken);
528523

529524
Assert.NotNull(result);
530525
Assert.NotEmpty(result.Content);
531526
Assert.Equal("text", result.Content[0].Type);
532527
Assert.Contains("LLM sampling result:", result.Content[0].Text);
533528
Assert.Contains("Eiffel", result.Content[0].Text);
534529
}
530+
531+
private static void SkipTestIfNoOpenAIKey()
532+
{
533+
if (string.IsNullOrEmpty(s_openAIKey))
534+
{
535+
throw SkipException.ForSkip("No OpenAI key provided. Skipping test.");
536+
}
537+
}
535538
}

tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<PackageReference Include="Microsoft.NET.Test.Sdk" />
1919
<PackageReference Include="Moq" />
2020
<PackageReference Include="System.Linq.AsyncEnumerable" />
21-
<PackageReference Include="xunit" />
21+
<PackageReference Include="xunit.v3" />
2222
<PackageReference Include="xunit.runner.visualstudio">
2323
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2424
<PrivateAssets>all</PrivateAssets>

0 commit comments

Comments
 (0)