microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
devtools-port-no-auth

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Tests/Microsoft.Teams.Plugins.External.McpClient.Tests/McpClientPluginTests.cs

184lines · modecode

1using System.Text.Json;
2
3using Microsoft.Teams.AI;
4using Microsoft.Teams.AI.Prompts;
5
6using Moq;
7
8namespace Microsoft.Teams.Plugins.External.McpClient.Tests;
9
10public class McpClientPluginTests
11{
12 [Fact]
13 public void Test_Constructor_SetsDefaults_AndInitializesCacheTimestamps()
14 {
15 // Arrange
16 var cache = new Dictionary<string, McpCachedValue>
17 {
18 ["http://example.org"] = new McpCachedValue
19 {
20 AvailableTools = new List<McpToolDetails> {
21 new McpToolDetails { Name = "tool1", Description = "d", InputSchema = JsonDocument.Parse("{} ").RootElement }
22 },
23 LastFetched = null
24 }
25 };
26 var logger = new Mock<Microsoft.Teams.Common.Logging.ILogger>(MockBehavior.Strict);
27 logger.Setup(l => l.Child(It.IsAny<string>())).Returns(logger.Object);
28
29 // Act
30 var plugin = new McpClientPlugin(new McpClientPluginOptions
31 {
32 Name = "TestPlugin",
33 Version = "1.2.3",
34 Cache = cache,
35 Logger = logger.Object
36 });
37
38 // Assert
39 Assert.Equal("TestPlugin", plugin.Name);
40 Assert.Equal("1.2.3", plugin.Version);
41 Assert.True(cache["http://example.org"].LastFetched.HasValue);
42 }
43
44 [Fact]
45 public void Test_UseMcpServer_WithAvailableTools_PopulatesCache()
46 {
47 // Arrange
48 var plugin = new McpClientPlugin();
49 var tools = new List<McpToolDetails>
50 {
51 new McpToolDetails { Name = "alpha", Description = "desc", InputSchema = JsonDocument.Parse("{} ").RootElement }
52 };
53
54 // Act
55 var returned = plugin.UseMcpServer("http://server-a", new McpClientPluginParams { AvailableTools = tools });
56
57 // Assert
58 Assert.Same(plugin, returned);
59 Assert.True(plugin.Cache.ContainsKey("http://server-a"));
60 Assert.Equal("alpha", plugin.Cache["http://server-a"].AvailableTools![0].Name);
61 Assert.True(plugin.Cache["http://server-a"].LastFetched.HasValue);
62 }
63
64 [Fact]
65 public void Test_UseMcpServer_WithoutAvailableTools_DoesNotPopulateCacheImmediately()
66 {
67 // Arrange
68 var plugin = new McpClientPlugin();
69
70 // Act
71 plugin.UseMcpServer("http://server-b");
72
73 // Assert
74 Assert.False(plugin.Cache.ContainsKey("http://server-b"));
75 }
76
77 [Fact]
78 public async Task OnBuildFunctions_AddsFunctionsFromCache()
79 {
80 // Arrange
81 var plugin = new McpClientPlugin();
82 var tools = new List<McpToolDetails>
83 {
84 new McpToolDetails { Name = "doThing", Description = "Does a thing", InputSchema = JsonDocument.Parse("{} ").RootElement }
85 };
86 plugin.UseMcpServer("http://server-c", new McpClientPluginParams { AvailableTools = tools });
87 var prompt = new Mock<IChatPrompt<object>>().Object; // Not used internally beyond type
88 var functions = new FunctionCollection();
89
90 // Act
91 var result = await plugin.OnBuildFunctions(prompt, functions, CancellationToken.None);
92
93 // Assert
94 Assert.True(result.Has("doThing"));
95 Assert.Single(result.Names);
96 }
97
98 [Fact]
99 public void Test_CreateTransport_ReturnsNonNull_ForEachTransport()
100 {
101 // Arrange
102 var plugin = new McpClientPlugin();
103 var url = new Uri("http://localhost");
104
105 // Act & Assert
106 foreach (McpClientTransport mode in Enum.GetValues(typeof(McpClientTransport)))
107 {
108 var transport = plugin.CreateTransport(url, mode, null);
109 Assert.NotNull(transport);
110 }
111 }
112
113 [Fact]
114 public void Test_CreateFunctionFromTool_ReturnsFunction()
115 {
116 // Arrange
117 var plugin = new McpClientPlugin();
118 var url = new Uri("http://localhost");
119 var tool = new McpToolDetails { Name = "toolX", Description = "desc", InputSchema = JsonDocument.Parse("{} ").RootElement };
120 var paramsObj = new McpClientPluginParams();
121
122 // Act
123 var function = plugin.CreateFunctionFromTool(url, tool, paramsObj);
124
125 // Assert
126 Assert.Equal("toolX", function.Name);
127 Assert.Equal("desc", function.Description);
128 Assert.NotNull(function.Parameters);
129 }
130
131 [Fact]
132 public async Task FetchToolsIfNeeded_NoServersWithFetchNeeded_NoChanges()
133 {
134 // Arrange
135 var plugin = new McpClientPlugin();
136 plugin.UseMcpServer("http://server-d", new McpClientPluginParams
137 {
138 AvailableTools = new List<McpToolDetails> { new McpToolDetails { Name = "t", Description = "d", InputSchema = JsonDocument.Parse("{} ").RootElement } }
139 });
140 var before = plugin.Cache["http://server-d"].LastFetched;
141
142 // Act
143 await plugin.FetchToolsIfNeeded();
144
145 // Assert
146 var after = plugin.Cache["http://server-d"].LastFetched;
147 Assert.Equal(before, after);
148 }
149
150 [Fact]
151 public async Task FetchToolsFromServer_InvalidEndpoint_ThrowsOrReturns()
152 {
153 // Arrange
154 var plugin = new McpClientPlugin();
155 var url = new Uri("http://127.0.0.1:59999");
156 var p = new McpClientPluginParams();
157
158 // Act & Assert
159 try
160 {
161 var task = plugin.FetchToolsFromServer(url, p);
162 await Assert.ThrowsAnyAsync<Exception>(async () => await task);
163 }
164 catch (Exception)
165 {
166 // Acceptable: network failure may bubble earlier
167 Assert.True(true);
168 }
169 }
170
171 [Fact]
172 public async Task CallMcpTool_InvalidEndpoint_Throws()
173 {
174 // Arrange
175 var plugin = new McpClientPlugin();
176 var url = new Uri("http://127.0.0.1:60001");
177 var tool = new McpToolDetails { Name = "missing", Description = "", InputSchema = JsonDocument.Parse("{} ").RootElement };
178 var p = new McpClientPluginParams();
179 var args = new Dictionary<string, object?>();
180
181 // Act & Assert
182 await Assert.ThrowsAnyAsync<Exception>(async () => await plugin.CallMcpTool(url, tool, args, p));
183 }
184}