Skip to content

Commit e9bb15f

Browse files
author
Esteban Solano
committed
+ code coverage for ClientOptions/Capabilities code
1 parent 251461b commit e9bb15f

2 files changed

Lines changed: 77 additions & 6 deletions

File tree

tests/ModelContextProtocol.Tests/Client/McpClientExtensionsTests.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,9 @@ public async Task CreateSamplingHandler_ShouldHandleResourceMessages()
151151
Content = new Content
152152
{
153153
Type = "resource",
154-
Resource = new ResourceContents
154+
Resource = new BlobResourceContents
155155
{
156-
Text = "Resource text",
157-
Blob = Convert.ToBase64String(new byte[] { 4, 5, 6 }),
156+
Blob = "Resource text",
158157
MimeType = "application/octet-stream"
159158
}
160159
}
@@ -188,7 +187,7 @@ public async Task CreateSamplingHandler_ShouldHandleResourceMessages()
188187
Assert.Equal("endTurn", result.StopReason);
189188
}
190189

191-
public ValueTask DisposeAsync()
190+
public async ValueTask DisposeAsync()
192191
{
193192
await _cts.CancelAsync();
194193

tests/ModelContextProtocol.Tests/Client/McpClientFactoryTests.cs

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using System.Threading.Channels;
2+
using Microsoft.Extensions.Logging;
23
using ModelContextProtocol.Client;
34
using ModelContextProtocol.Protocol.Messages;
45
using ModelContextProtocol.Protocol.Transport;
56
using ModelContextProtocol.Protocol.Types;
7+
using Moq;
68

79
namespace ModelContextProtocol.Tests.Client;
810

@@ -186,7 +188,67 @@ public async Task McpFactory_WithInvalidTransportOptions_ThrowsFormatException(s
186188
await Assert.ThrowsAsync<ArgumentException>(() => McpClientFactory.CreateAsync(config, _defaultOptions, cancellationToken: TestContext.Current.CancellationToken));
187189
}
188190

189-
private sealed class NopTransport : ITransport, IClientTransport
191+
[Theory]
192+
[InlineData(typeof(NopTransport))]
193+
[InlineData(typeof(FailureTransport))]
194+
public async Task CreateAsync_WithCapabilities(Type transportType)
195+
{
196+
// Arrange
197+
var serverConfig = new McpServerConfig
198+
{
199+
Id = "TestServer",
200+
Name = "TestServer",
201+
TransportType = "stdio",
202+
Location = "test-location"
203+
};
204+
205+
var clientOptions = new McpClientOptions
206+
{
207+
ClientInfo = new Implementation
208+
{
209+
Name = "TestClient",
210+
Version = "1.0.0.0"
211+
},
212+
Capabilities = new ClientCapabilities
213+
{
214+
Sampling = new SamplingCapability
215+
{
216+
SamplingHandler = (c, t) => Task.FromResult(
217+
new CreateMessageResult {
218+
Content = new Content { Text = "result" },
219+
Model = "test-model",
220+
Role = "test-role",
221+
StopReason = "endTurn"
222+
}),
223+
},
224+
Roots = new RootsCapability
225+
{
226+
ListChanged = true,
227+
RootsHandler = (t, r) => Task.FromResult(new ListRootsResult { Roots = [] }),
228+
}
229+
}
230+
};
231+
232+
var clientTransport = (IClientTransport?)Activator.CreateInstance(transportType);
233+
IMcpClient? client = null;
234+
235+
var actionTask = McpClientFactory.CreateAsync(serverConfig, clientOptions, (config, logger) => clientTransport ?? new NopTransport(), new Mock<ILoggerFactory>().Object, CancellationToken.None);
236+
237+
// Act
238+
if (clientTransport is FailureTransport)
239+
{
240+
var exception = await Assert.ThrowsAsync<InvalidOperationException>(async() => await actionTask);
241+
Assert.Equal(FailureTransport.ExpectedMessage, exception.Message);
242+
}
243+
else
244+
{
245+
client = await actionTask;
246+
247+
// Assert
248+
Assert.NotNull(client);
249+
}
250+
}
251+
private class NopTransport : ITransport, IClientTransport
190252
{
191253
private readonly Channel<IJsonRpcMessage> _channel = Channel.CreateUnbounded<IJsonRpcMessage>();
192254

@@ -198,7 +260,7 @@ private sealed class NopTransport : ITransport, IClientTransport
198260

199261
public ValueTask DisposeAsync() => default;
200262

201-
public Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
263+
public virtual Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
202264
{
203265
switch (message)
204266
{
@@ -223,4 +285,14 @@ public Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancella
223285
return Task.CompletedTask;
224286
}
225287
}
288+
289+
private sealed class FailureTransport : NopTransport
290+
{
291+
public const string ExpectedMessage = "Something failed";
292+
293+
public override Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
294+
{
295+
throw new InvalidOperationException(ExpectedMessage);
296+
}
297+
}
226298
}

0 commit comments

Comments
 (0)