using Microsoft.Extensions.DependencyInjection; using ModelContextProtocol.Client; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; using System.ComponentModel; namespace ModelContextProtocol.Tests.Client; public class McpClientResourceTemplateConstructorTests : ClientServerTestBase { public McpClientResourceTemplateConstructorTests(ITestOutputHelper outputHelper) : base(outputHelper) { } protected override void ConfigureServices(ServiceCollection services, IMcpServerBuilder mcpServerBuilder) { mcpServerBuilder.WithResources(); } [McpServerResourceType] private sealed class FileTemplateResources { [McpServerResource, Description("A file template")] public static string FileTemplate([Description("The file path")] string path) => $"Content for {path}"; } [Fact] public async Task Constructor_WithValidParameters_CreatesInstance() { await using McpClient client = await CreateMcpClientForServer(); var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken); var originalTemplate = templates.First(); var templateDefinition = originalTemplate.ProtocolResourceTemplate; var newTemplate = new McpClientResourceTemplate(client, templateDefinition); Assert.NotNull(newTemplate); Assert.Equal("file_template", newTemplate.Name); Assert.Equal("A file template", newTemplate.Description); Assert.Same(templateDefinition, newTemplate.ProtocolResourceTemplate); } [Fact] public void Constructor_WithNullClient_ThrowsArgumentNullException() { var templateDefinition = new ResourceTemplate { UriTemplate = "file:///{path}", Name = "test", Description = "Test template" }; Assert.Throws("client", () => new McpClientResourceTemplate(null!, templateDefinition)); } [Fact] public async Task Constructor_WithNullResourceTemplate_ThrowsArgumentNullException() { await using McpClient client = await CreateMcpClientForServer(); Assert.Throws("resourceTemplate", () => new McpClientResourceTemplate(client, null!)); } [Fact] public async Task ReuseResourceTemplateDefinition_PreservesTemplateMetadata() { await using McpClient client = await CreateMcpClientForServer(); var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken); var originalTemplate = templates.First(); var templateDefinition = originalTemplate.ProtocolResourceTemplate; var reusedTemplate = new McpClientResourceTemplate(client, templateDefinition); Assert.Equal(originalTemplate.Name, reusedTemplate.Name); Assert.Equal(originalTemplate.Description, reusedTemplate.Description); Assert.Equal(originalTemplate.UriTemplate, reusedTemplate.UriTemplate); Assert.Equal(originalTemplate.ProtocolResourceTemplate.Name, reusedTemplate.ProtocolResourceTemplate.Name); Assert.Equal(originalTemplate.ProtocolResourceTemplate.Description, reusedTemplate.ProtocolResourceTemplate.Description); } [Fact] public async Task ManuallyConstructedResourceTemplate_CreatesValidInstance() { await using McpClient client = await CreateMcpClientForServer(); var manualTemplate = new ResourceTemplate { UriTemplate = "file:///{path}", Name = "file_template", Description = "A file template" }; var clientTemplate = new McpClientResourceTemplate(client, manualTemplate); Assert.NotNull(clientTemplate); Assert.Equal("file_template", clientTemplate.Name); Assert.Equal("A file template", clientTemplate.Description); Assert.Equal("file:///{path}", clientTemplate.UriTemplate); } }