Repository: microsoft/semantic-kernel
File: dotnet/src/Connectors/Connectors.Google.UnitTests/Core/Gemini/Clients/GeminiChatClientFunctionCallingTests.cs (C#)

Code before:

        this._httpClient = new HttpClient(this._messageHandlerStub, false);

        var kernelPlugin = KernelPluginFactory.CreateFromFunctions("TimePlugin", new[]
        {
            KernelFunctionFactory.CreateFromMethod((string? format = null)
                => DateTime.Now.Date.ToString(format, CultureInfo.InvariantCulture), "Date", "TimePlugin.Date"),
            KernelFunctionFactory.CreateFromMethod(()
                    => DateTime.Now.ToString("", CultureInfo.InvariantCulture), "Now", "TimePlugin.Now",
                parameters: [new KernelParameterMetadata("param1") { ParameterType = typeof(string), Description = "desc", IsRequired = false }]),
        });
        IList<KernelFunctionMetadata> functions = kernelPlugin.GetFunctionsMetadata();

        this._timePluginDate = functions[0].ToGeminiFunction();
        this._timePluginNow = functions[1].ToGeminiFunction();

        this._kernelWithFunctions = new Kernel();
        this._kernelWithFunctions.Plugins.Add(kernelPlugin);
    }

    [Fact]
    public async Task ChatClientWithFunctionChoiceBehaviorAutoShouldIncludeToolsInRequestAsync()
    {
        // Arrange
        var chatCompletionService = this.CreateChatCompletionService();
        var chatClient = chatCompletionService.AsChatClient();
        var chatHistory = new ChatHistory();
        chatHistory.AddUserMessage("What time is it?");

        var settings = new GeminiPromptExecutionSettings
        {
            FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
        };

        // Act
        await chatCompletionService.GetChatMessageContentAsync(chatHistory, settings, this._kernelWithFunctions);

        // Assert
        GeminiRequest? request = JsonSerializer.Deserialize<GeminiRequest>(this._messageHandlerStub.RequestContent);
        Assert.NotNull(request);
        Assert.NotNull(request.Tools);
        Assert.Collection(request.Tools[0].Functions,
            item => Assert.Equal(this._timePluginDate.FullyQualifiedName, item.Name),
            item => Assert.Equal(this._timePluginNow.FullyQualifiedName, item.Name));
    }

    [Fact]
    public async Task ChatClientWithFunctionChoiceBehaviorShouldReturnFunctionCallContentAsync()
    {
        // Arrange
        this._messageHandlerStub.ResponseToReturn.Content = new StringContent(this._responseContentWithFunction);

Review comment (suggestion):
@copilot, this test created a chatClient but then doesn't use it. All of the tests in this file should _only_ make calls on the resulting IChatClient; they should not be making calls through the IChatCompletionService other than to AsChatClient to get the resulting IChatClient to use. The purpose of this file is to exercise everything via IChatClient and ensure the right messages are being sent and received.

Code after:

        var kernelPlugin = KernelPluginFactory.CreateFromFunctions("TimePlugin", new[]
        {
            KernelFunctionFactory.CreateFromMethod((string? format = null)
                => DateTime.Now.Date.ToString(format, CultureInfo.InvariantCulture), "Date", "TimePlugin.Date"),
            KernelFunctionFactory.CreateFromMethod(()
                    => DateTime.Now.ToString("", CultureInfo.InvariantCulture), "Now", "TimePlugin.Now",
                parameters: [new KernelParameterMetadata("param1") { ParameterType = typeof(string), Description = "desc", IsRequired = false }]),
        });
        IList<KernelFunctionMetadata> functions = kernelPlugin.GetFunctionsMetadata();

        this._timePluginDate = functions[0].ToGeminiFunction();
        this._timePluginNow = functions[1].ToGeminiFunction();

        this._kernelWithFunctions = new Kernel();
        this._kernelWithFunctions.Plugins.Add(kernelPlugin);
    }

    [Fact]
    public async Task ChatClientShouldConvertToIChatClientSuccessfullyAsync()
    {
        // Arrange
        var chatCompletionService = this.CreateChatCompletionService();

        // Act
        var chatClient = chatCompletionService.AsChatClient();

        // Assert - Verify conversion works
        Assert.NotNull(chatClient);
        Assert.IsAssignableFrom<IChatClient>(chatClient);

        // Verify we can make a basic call through IChatClient
        var messages = new List<ChatMessage>
        {
            new(ChatRole.User, "What time is it?")
        };

        var response = await chatClient.GetResponseAsync(messages);

        Assert.NotNull(response);
        Assert.NotEmpty(response.Messages);
    }

    [Fact]
    public async Task ChatClientShouldReceiveFunctionCallsInResponseAsync()
    {
        // Arrange
        this._messageHandlerStub.ResponseToReturn.Content = new StringContent(this._responseContentWithFunction);
        var chatCompletionService = this.CreateChatCompletionService();
        var chatClient = chatCompletionService.AsChatClient();