11using System ;
22using System . ClientModel ;
3- using System . ClientModel . Primitives ;
43using System . Collections . Generic ;
5- using System . IO ;
64using System . Linq ;
7- using System . Net . Http ;
85using System . Threading ;
96using System . Threading . Tasks ;
107using Moq ;
@@ -17,57 +14,8 @@ namespace OpenAI.Tests.Utility;
1714
1815[ TestFixture ]
1916[ Category ( "Utility" ) ]
20- public class ChatToolsTests
17+ public class ChatToolsTests : ToolsTestsBase
2118{
22- private class TestTools
23- {
24- public static string Echo ( string message ) => message ;
25- public static int Add ( int a , int b ) => a + b ;
26- public static double Multiply ( double x , double y ) => x * y ;
27- public static bool IsGreaterThan ( long value1 , long value2 ) => value1 > value2 ;
28- public static float Divide ( float numerator , float denominator ) => numerator / denominator ;
29- public static string ConcatWithBool ( string text , bool flag ) => $ "{ text } :{ flag } ";
30- }
31-
32- private class TestToolsAsync
33- {
34- public static async Task < string > EchoAsync ( string message )
35- {
36- await Task . Delay ( 1 ) ; // Simulate async work
37- return message ;
38- }
39-
40- public static async Task < int > AddAsync ( int a , int b )
41- {
42- await Task . Delay ( 1 ) ; // Simulate async work
43- return a + b ;
44- }
45-
46- public static async Task < double > MultiplyAsync ( double x , double y )
47- {
48- await Task . Delay ( 1 ) ; // Simulate async work
49- return x * y ;
50- }
51-
52- public static async Task < bool > IsGreaterThanAsync ( long value1 , long value2 )
53- {
54- await Task . Delay ( 1 ) ; // Simulate async work
55- return value1 > value2 ;
56- }
57-
58- public static async Task < float > DivideAsync ( float numerator , float denominator )
59- {
60- await Task . Delay ( 1 ) ; // Simulate async work
61- return numerator / denominator ;
62- }
63-
64- public static async Task < string > ConcatWithBoolAsync ( string text , bool flag )
65- {
66- await Task . Delay ( 1 ) ; // Simulate async work
67- return $ "{ text } :{ flag } ";
68- }
69- }
70-
7119 private Mock < EmbeddingClient > mockEmbeddingClient ;
7220
7321 [ SetUp ]
@@ -234,9 +182,6 @@ public async Task AddMcpToolsAsync_AddsToolsCorrectly()
234182 {
235183 // Arrange
236184 var mcpEndpoint = new Uri ( "http://localhost:1234" ) ;
237- var mockMcpClient = new Mock < McpClient > ( mcpEndpoint ) ;
238- var tools = new ChatTools ( ) ;
239-
240185 var mockToolsResponse = BinaryData . FromString ( @"
241186 {
242187 ""tools"": [
@@ -279,42 +224,48 @@ public async Task AddMcpToolsAsync_AddsToolsCorrectly()
279224 ]
280225 }" ) ;
281226
282- mockMcpClient . Setup ( c => c . StartAsync ( ) )
283- . Returns ( Task . CompletedTask ) ;
284- mockMcpClient . Setup ( c => c . ListToolsAsync ( ) )
285- . ReturnsAsync ( mockToolsResponse ) ;
286- mockMcpClient . Setup ( c => c . CallToolAsync ( It . IsAny < string > ( ) , It . IsAny < BinaryData > ( ) ) )
287- . ReturnsAsync ( BinaryData . FromString ( "\" test result\" " ) ) ;
288- mockMcpClient . SetupGet ( c => c . Endpoint )
289- . Returns ( mcpEndpoint ) ;
227+ var responsesByTool = new Dictionary < string , string >
228+ {
229+ [ "mcp-tool-1" ] = "\" tool1 result\" " ,
230+ [ "mcp-tool-2" ] = "\" tool2 result\" "
231+ } ;
232+
233+ var testClient = new TestMcpClient (
234+ mcpEndpoint ,
235+ mockToolsResponse ,
236+ toolName => BinaryData . FromString ( responsesByTool [ toolName . Split ( '_' ) . Last ( ) ] ) ) ;
237+ var tools = new ChatTools ( ) ;
290238
291239 // Act
292- await tools . AddMcpToolsAsync ( mockMcpClient . Object ) ;
240+ await tools . AddMcpToolsAsync ( testClient ) ;
293241
294242 // Assert
295243 Assert . That ( tools . Tools , Has . Count . EqualTo ( 2 ) ) ;
296244 var toolNames = tools . Tools . Select ( t => t . FunctionName ) . ToList ( ) ;
297245 Assert . That ( toolNames , Contains . Item ( "localhost1234_-_mcp-tool-1" ) ) ;
298246 Assert . That ( toolNames , Contains . Item ( "localhost1234_-_mcp-tool-2" ) ) ;
299247
300- // Verify we can call the tools
301- var toolCall = ChatToolCall . CreateFunctionToolCall ( "call1" , "localhost1234_-_mcp-tool-1" , BinaryData . FromString ( @"{""param1"": ""test""}" ) ) ;
302- var result = await tools . CallAsync ( new [ ] { toolCall } ) ;
303- var resultsList = result . ToList ( ) ;
248+ // Verify we can call the tools with different responses
249+ var toolCalls = new [ ]
250+ {
251+ ChatToolCall . CreateFunctionToolCall ( "call1" , "localhost1234_-_mcp-tool-1" , BinaryData . FromString ( @"{""param1"": ""test""}" ) ) ,
252+ ChatToolCall . CreateFunctionToolCall ( "call2" , "localhost1234_-_mcp-tool-2" , BinaryData . FromString ( @"{""param2"": ""test""}" ) )
253+ } ;
254+ var results = await tools . CallAsync ( toolCalls ) ;
255+ var resultsList = results . ToList ( ) ;
304256
305- Assert . That ( resultsList , Has . Count . EqualTo ( 1 ) ) ;
257+ Assert . That ( resultsList , Has . Count . EqualTo ( 2 ) ) ;
306258 Assert . That ( resultsList [ 0 ] . ToolCallId , Is . EqualTo ( "call1" ) ) ;
307- Assert . That ( resultsList [ 0 ] . Content [ 0 ] . Text , Is . EqualTo ( "\" test result\" " ) ) ;
259+ Assert . That ( resultsList [ 0 ] . Content [ 0 ] . Text , Is . EqualTo ( "\" tool1 result\" " ) ) ;
260+ Assert . That ( resultsList [ 1 ] . ToolCallId , Is . EqualTo ( "call2" ) ) ;
261+ Assert . That ( resultsList [ 1 ] . Content [ 0 ] . Text , Is . EqualTo ( "\" tool2 result\" " ) ) ;
308262 }
309263
310264 [ Test ]
311265 public async Task CreateCompletionOptions_WithMaxToolsParameter_FiltersTools ( )
312266 {
313267 // Arrange
314268 var mcpEndpoint = new Uri ( "http://localhost:1234" ) ;
315- var mockMcpClient = new Mock < McpClient > ( mcpEndpoint ) ;
316- var tools = new ChatTools ( mockEmbeddingClient . Object ) ;
317-
318269 var mockToolsResponse = BinaryData . FromString ( @"
319270 {
320271 ""tools"": [
@@ -364,7 +315,7 @@ public async Task CreateCompletionOptions_WithMaxToolsParameter_FiltersTools()
364315 ]
365316 }" ) ;
366317
367- // Setup mock responses
318+ // Setup mock embedding responses
368319 var embeddings = new [ ]
369320 {
370321 OpenAIEmbeddingsModelFactory . OpenAIEmbedding ( vector : new [ ] { 0.8f , 0.5f } ) ,
@@ -377,15 +328,6 @@ public async Task CreateCompletionOptions_WithMaxToolsParameter_FiltersTools()
377328 usage : OpenAIEmbeddingsModelFactory . EmbeddingTokenUsage ( 30 , 30 ) ) ;
378329 var mockResponse = new MockPipelineResponse ( 200 ) ;
379330
380- mockMcpClient . Setup ( c => c . StartAsync ( ) )
381- . Returns ( Task . CompletedTask ) ;
382- mockMcpClient . Setup ( c => c . ListToolsAsync ( ) )
383- . ReturnsAsync ( mockToolsResponse ) ;
384- mockMcpClient . Setup ( c => c . CallToolAsync ( "math-tool" , It . IsAny < BinaryData > ( ) ) )
385- . ReturnsAsync ( BinaryData . FromString ( "\" math-tool result\" " ) ) ;
386- mockMcpClient . SetupGet ( c => c . Endpoint )
387- . Returns ( mcpEndpoint ) ;
388-
389331 mockEmbeddingClient
390332 . Setup ( c => c . GenerateEmbeddingAsync (
391333 It . IsAny < string > ( ) ,
@@ -400,8 +342,14 @@ public async Task CreateCompletionOptions_WithMaxToolsParameter_FiltersTools()
400342 It . IsAny < CancellationToken > ( ) ) )
401343 . ReturnsAsync ( ClientResult . FromValue ( embeddingCollection , mockResponse ) ) ;
402344
345+ var testClient = new TestMcpClient (
346+ mcpEndpoint ,
347+ mockToolsResponse ,
348+ toolName => BinaryData . FromString ( $ "\" { toolName } result\" ") ) ;
349+ var tools = new ChatTools ( mockEmbeddingClient . Object ) ;
350+
403351 // Add the tools
404- await tools . AddMcpToolsAsync ( mockMcpClient . Object ) ;
352+ await tools . AddMcpToolsAsync ( testClient ) ;
405353
406354 // Act & Assert
407355 // Test with maxTools = 1
@@ -420,9 +368,5 @@ public async Task CreateCompletionOptions_WithMaxToolsParameter_FiltersTools()
420368 var result = await tools . CallAsync ( new [ ] { toolCall } ) ;
421369 Assert . That ( result . First ( ) . ToolCallId , Is . EqualTo ( "call1" ) ) ;
422370 Assert . That ( result . First ( ) . Content [ 0 ] . Text , Is . EqualTo ( "\" math-tool result\" " ) ) ;
423-
424- // Verify expected interactions
425- mockMcpClient . Verify ( c => c . StartAsync ( ) , Times . Once ) ;
426- mockMcpClient . Verify ( c => c . ListToolsAsync ( ) , Times . Once ) ;
427371 }
428372}
0 commit comments