From c0821ab7d4d471859c1fb689faa4e88169c0a58d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 22 Jan 2026 00:03:05 +0000
Subject: [PATCH 1/6] Initial plan
From 993d3b15021fb3580c62f2801b5fdbccc34e52ee Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 22 Jan 2026 00:13:19 +0000
Subject: [PATCH 2/6] Add unit tests for Microsoft.Agents.AI.OpenAI to improve
code coverage
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
---
.../Microsoft.Agents.AI.OpenAI.csproj | 4 +
...atCompletionUpdateCollectionResultTests.cs | 110 +++++
...mingResponseUpdateCollectionResultTests.cs | 191 +++++++++
.../StreamingUpdatePipelineResponseTests.cs | 154 +++++++
.../AIAgentWithOpenAIExtensionsTests.cs | 167 ++++++++
.../AgentResponseExtensionsTests.cs | 145 +++++++
.../OpenAIAssistantClientExtensionsTests.cs | 382 ++++++++++++++++++
7 files changed, 1153 insertions(+)
create mode 100644 dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
diff --git a/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj b/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj
index bfcf6e5263..3de68137ba 100644
--- a/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj
+++ b/dotnet/src/Microsoft.Agents.AI.OpenAI/Microsoft.Agents.AI.OpenAI.csproj
@@ -17,6 +17,10 @@
+
+
+
+
Microsoft Agent Framework OpenAI
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs
new file mode 100644
index 0000000000..d682d7e53b
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs
@@ -0,0 +1,110 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.ClientModel;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Extensions.AI;
+using OpenAI.Chat;
+
+namespace Microsoft.Agents.AI.OpenAI.UnitTests.ChatClient;
+
+///
+/// Unit tests for the class.
+///
+public sealed class AsyncStreamingChatCompletionUpdateCollectionResultTests
+{
+ ///
+ /// Verify that GetContinuationToken returns null.
+ ///
+ [Fact]
+ public void GetContinuationToken_ReturnsNull()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingChatCompletionUpdateCollectionResult(updates);
+
+ // Act
+ ContinuationToken? token = collectionResult.GetContinuationToken(null!);
+
+ // Assert
+ Assert.Null(token);
+ }
+
+ ///
+ /// Verify that GetRawPagesAsync returns a single page.
+ ///
+ [Fact]
+ public async Task GetRawPagesAsync_ReturnsSinglePageAsync()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingChatCompletionUpdateCollectionResult(updates);
+
+ // Act
+ List pages = [];
+ await foreach (ClientResult page in collectionResult.GetRawPagesAsync())
+ {
+ pages.Add(page);
+ }
+
+ // Assert
+ Assert.Single(pages);
+ }
+
+ ///
+ /// Verify that iterating through the collection yields streaming updates.
+ ///
+ [Fact]
+ public async Task IterateCollection_YieldsUpdatesAsync()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingChatCompletionUpdateCollectionResult(updates);
+
+ // Act
+ List results = [];
+ await foreach (StreamingChatCompletionUpdate update in collectionResult)
+ {
+ results.Add(update);
+ }
+
+ // Assert
+ Assert.Single(results);
+ }
+
+ ///
+ /// Verify that iterating through the collection with multiple updates yields all updates.
+ ///
+ [Fact]
+ public async Task IterateCollection_WithMultipleUpdates_YieldsAllUpdatesAsync()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateMultipleTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingChatCompletionUpdateCollectionResult(updates);
+
+ // Act
+ List results = [];
+ await foreach (StreamingChatCompletionUpdate update in collectionResult)
+ {
+ results.Add(update);
+ }
+
+ // Assert
+ Assert.Equal(3, results.Count);
+ }
+
+ private static async IAsyncEnumerable CreateTestUpdatesAsync()
+ {
+ yield return new AgentResponseUpdate(ChatRole.Assistant, "test");
+ await Task.CompletedTask;
+ }
+
+ private static async IAsyncEnumerable CreateMultipleTestUpdatesAsync()
+ {
+ yield return new AgentResponseUpdate(ChatRole.Assistant, "first");
+ yield return new AgentResponseUpdate(ChatRole.Assistant, "second");
+ yield return new AgentResponseUpdate(ChatRole.Assistant, "third");
+ await Task.CompletedTask;
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
new file mode 100644
index 0000000000..6cb6216f5d
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
@@ -0,0 +1,191 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.ClientModel;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Extensions.AI;
+using OpenAI.Responses;
+
+namespace Microsoft.Agents.AI.OpenAI.UnitTests.ChatClient;
+
+///
+/// Unit tests for the class.
+///
+public sealed class AsyncStreamingResponseUpdateCollectionResultTests
+{
+ ///
+ /// Verify that GetContinuationToken returns null.
+ ///
+ [Fact]
+ public void GetContinuationToken_ReturnsNull()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingResponseUpdateCollectionResult(updates);
+
+ // Act
+ ContinuationToken? token = collectionResult.GetContinuationToken(null!);
+
+ // Assert
+ Assert.Null(token);
+ }
+
+ ///
+ /// Verify that GetRawPagesAsync returns a single page.
+ ///
+ [Fact]
+ public async Task GetRawPagesAsync_ReturnsSinglePageAsync()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingResponseUpdateCollectionResult(updates);
+
+ // Act
+ List pages = [];
+ await foreach (ClientResult page in collectionResult.GetRawPagesAsync())
+ {
+ pages.Add(page);
+ }
+
+ // Assert
+ Assert.Single(pages);
+ }
+
+ ///
+ /// Verify that iterating through the collection yields streaming updates when RawRepresentation is a StreamingResponseUpdate.
+ ///
+ [Fact]
+ public async Task IterateCollection_WithStreamingResponseUpdateRawRepresentation_YieldsUpdatesAsync()
+ {
+ // Arrange
+ StreamingResponseUpdate rawUpdate = CreateStreamingResponseUpdate();
+ IAsyncEnumerable updates = CreateTestUpdatesWithRawRepresentationAsync(rawUpdate);
+ AsyncCollectionResult collectionResult = new AsyncStreamingResponseUpdateCollectionResult(updates);
+
+ // Act
+ List results = [];
+ await foreach (StreamingResponseUpdate update in collectionResult)
+ {
+ results.Add(update);
+ }
+
+ // Assert
+ Assert.Single(results);
+ Assert.Same(rawUpdate, results[0]);
+ }
+
+ ///
+ /// Verify that iterating through the collection yields updates when RawRepresentation is a ChatResponseUpdate containing a StreamingResponseUpdate.
+ ///
+ [Fact]
+ public async Task IterateCollection_WithChatResponseUpdateContainingStreamingResponseUpdate_YieldsUpdatesAsync()
+ {
+ // Arrange
+ StreamingResponseUpdate rawUpdate = CreateStreamingResponseUpdate();
+ ChatResponseUpdate chatResponseUpdate = new() { RawRepresentation = rawUpdate };
+ IAsyncEnumerable updates = CreateTestUpdatesWithChatResponseUpdateAsync(chatResponseUpdate);
+ AsyncCollectionResult collectionResult = new AsyncStreamingResponseUpdateCollectionResult(updates);
+
+ // Act
+ List results = [];
+ await foreach (StreamingResponseUpdate update in collectionResult)
+ {
+ results.Add(update);
+ }
+
+ // Assert
+ Assert.Single(results);
+ Assert.Same(rawUpdate, results[0]);
+ }
+
+ ///
+ /// Verify that iterating through the collection skips updates when RawRepresentation is not a StreamingResponseUpdate.
+ ///
+ [Fact]
+ public async Task IterateCollection_WithNonStreamingResponseUpdateRawRepresentation_SkipsUpdateAsync()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ AsyncCollectionResult collectionResult = new AsyncStreamingResponseUpdateCollectionResult(updates);
+
+ // Act
+ List results = [];
+ await foreach (StreamingResponseUpdate update in collectionResult)
+ {
+ results.Add(update);
+ }
+
+ // Assert - should be empty since updates don't have StreamingResponseUpdate as RawRepresentation
+ Assert.Empty(results);
+ }
+
+ ///
+ /// Verify that iterating through the collection skips updates when RawRepresentation is a ChatResponseUpdate without StreamingResponseUpdate.
+ ///
+ [Fact]
+ public async Task IterateCollection_WithChatResponseUpdateWithoutStreamingResponseUpdate_SkipsUpdateAsync()
+ {
+ // Arrange
+ ChatResponseUpdate chatResponseUpdate = new() { RawRepresentation = "not a streaming update" };
+ IAsyncEnumerable updates = CreateTestUpdatesWithChatResponseUpdateAsync(chatResponseUpdate);
+ AsyncCollectionResult collectionResult = new AsyncStreamingResponseUpdateCollectionResult(updates);
+
+ // Act
+ List results = [];
+ await foreach (StreamingResponseUpdate update in collectionResult)
+ {
+ results.Add(update);
+ }
+
+ // Assert - should be empty since the ChatResponseUpdate doesn't have StreamingResponseUpdate as RawRepresentation
+ Assert.Empty(results);
+ }
+
+ private static async IAsyncEnumerable CreateTestUpdatesAsync()
+ {
+ yield return new AgentResponseUpdate(ChatRole.Assistant, "test");
+ await Task.CompletedTask;
+ }
+
+ private static async IAsyncEnumerable CreateTestUpdatesWithRawRepresentationAsync(object rawRepresentation)
+ {
+ AgentResponseUpdate update = new(ChatRole.Assistant, "test")
+ {
+ RawRepresentation = rawRepresentation
+ };
+ yield return update;
+ await Task.CompletedTask;
+ }
+
+ private static async IAsyncEnumerable CreateTestUpdatesWithChatResponseUpdateAsync(ChatResponseUpdate chatResponseUpdate)
+ {
+ AgentResponseUpdate update = new(ChatRole.Assistant, "test")
+ {
+ RawRepresentation = chatResponseUpdate
+ };
+ yield return update;
+ await Task.CompletedTask;
+ }
+
+ private static StreamingResponseUpdate CreateStreamingResponseUpdate()
+ {
+ const string Json = """
+ {
+ "type": "response.output_item.added",
+ "sequence_number": 1,
+ "output_index": 0,
+ "item": {
+ "id": "item_abc123",
+ "type": "message",
+ "status": "in_progress",
+ "role": "assistant",
+ "content": []
+ }
+ }
+ """;
+
+ return System.ClientModel.Primitives.ModelReaderWriter.Read(BinaryData.FromString(Json))!;
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
new file mode 100644
index 0000000000..19fb034bbd
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
@@ -0,0 +1,154 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.ClientModel.Primitives;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Microsoft.Agents.AI.OpenAI.UnitTests.ChatClient;
+
+///
+/// Unit tests for the class.
+///
+public sealed class StreamingUpdatePipelineResponseTests
+{
+ ///
+ /// Verify that Status property returns 200.
+ ///
+ [Fact]
+ public void Status_ReturnsOkStatus()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act
+ int status = response.Status;
+
+ // Assert
+ Assert.Equal(200, status);
+ }
+
+ ///
+ /// Verify that ReasonPhrase property returns "OK".
+ ///
+ [Fact]
+ public void ReasonPhrase_ReturnsOk()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act
+ string reasonPhrase = response.ReasonPhrase;
+
+ // Assert
+ Assert.Equal("OK", reasonPhrase);
+ }
+
+ ///
+ /// Verify that ContentStream getter returns null.
+ ///
+ [Fact]
+ public void ContentStream_Get_ReturnsNull()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act
+ System.IO.Stream? contentStream = response.ContentStream;
+
+ // Assert
+ Assert.Null(contentStream);
+ }
+
+ ///
+ /// Verify that ContentStream setter is a no-op.
+ ///
+ [Fact]
+ public void ContentStream_Set_IsNoOp()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+ var testStream = new System.IO.MemoryStream();
+
+ // Act
+ response.ContentStream = testStream;
+
+ // Assert - should remain null
+ Assert.Null(response.ContentStream);
+
+ testStream.Dispose();
+ }
+
+ ///
+ /// Verify that Content property returns empty BinaryData.
+ ///
+ [Fact]
+ public void Content_ReturnsEmptyBinaryData()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act
+ BinaryData content = response.Content;
+
+ // Assert
+ Assert.NotNull(content);
+ Assert.Equal(string.Empty, content.ToString());
+ }
+
+ ///
+ /// Verify that BufferContent throws NotSupportedException.
+ ///
+ [Fact]
+ public void BufferContent_ThrowsNotSupportedException()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act & Assert
+ var exception = Assert.Throws(() => response.BufferContent());
+ Assert.Contains("Buffering content is not supported", exception.Message);
+ }
+
+ ///
+ /// Verify that BufferContentAsync throws NotSupportedException.
+ ///
+ [Fact]
+ public async System.Threading.Tasks.Task BufferContentAsync_ThrowsNotSupportedExceptionAsync()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(
+ async () => await response.BufferContentAsync());
+ Assert.Contains("Buffering content asynchronously is not supported", exception.Message);
+ }
+
+ ///
+ /// Verify that Dispose does not throw.
+ ///
+ [Fact]
+ public void Dispose_DoesNotThrow()
+ {
+ // Arrange
+ IAsyncEnumerable updates = CreateTestUpdatesAsync();
+ PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
+
+ // Act & Assert - should not throw
+ response.Dispose();
+ }
+
+ private static async IAsyncEnumerable CreateTestUpdatesAsync()
+ {
+ yield return new AgentResponseUpdate(Microsoft.Extensions.AI.ChatRole.Assistant, "test");
+ await System.Threading.Tasks.Task.CompletedTask;
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs
index d29535eddb..a3cd7cd541 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs
@@ -7,6 +7,7 @@
using System.Threading.Tasks;
using Moq;
using Moq.Protected;
+using OpenAI.Responses;
using ChatMessage = Microsoft.Extensions.AI.ChatMessage;
using ChatRole = Microsoft.Extensions.AI.ChatRole;
using OpenAIChatMessage = OpenAI.Chat.ChatMessage;
@@ -208,4 +209,170 @@ private static async IAsyncEnumerable ToAsyncEnumerableAsyn
yield return await Task.FromResult(update);
}
}
+
+ #region ResponseItem overload tests
+
+ ///
+ /// Verify that RunAsync with ResponseItem throws ArgumentNullException when agent is null.
+ ///
+ [Fact]
+ public async Task RunAsync_ResponseItem_WithNullAgent_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange
+ AIAgent? agent = null;
+ IEnumerable messages = [ResponseItem.CreateUserMessageItem("Test message")];
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(
+ () => agent!.RunAsync(messages));
+
+ Assert.Equal("agent", exception.ParamName);
+ }
+
+ ///
+ /// Verify that RunAsync with ResponseItem throws ArgumentNullException when messages is null.
+ ///
+ [Fact]
+ public async Task RunAsync_ResponseItem_WithNullMessages_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange
+ var mockAgent = new Mock();
+ IEnumerable? messages = null;
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(
+ () => mockAgent.Object.RunAsync(messages!));
+
+ Assert.Equal("messages", exception.ParamName);
+ }
+
+ ///
+ /// Verify that the RunAsync with ResponseItem extension method calls the underlying agent's RunAsync with converted messages and parameters.
+ ///
+ [Fact]
+ public async Task RunAsync_ResponseItem_CallsUnderlyingAgentAsync()
+ {
+ // Arrange
+ var mockAgent = new Mock();
+ var mockThread = new Mock();
+ var options = new AgentRunOptions();
+ var cancellationToken = new CancellationToken(false);
+ const string TestMessageText = "Hello, assistant!";
+ const string ResponseText = "This is the assistant's response.";
+ IEnumerable responseItemMessages = [ResponseItem.CreateUserMessageItem(TestMessageText)];
+
+ var responseMessage = new ChatMessage(ChatRole.Assistant, [new TextContent(ResponseText)]);
+
+ mockAgent
+ .Protected()
+ .Setup>("RunCoreAsync",
+ ItExpr.IsAny>(),
+ ItExpr.IsAny(),
+ ItExpr.IsAny(),
+ ItExpr.IsAny())
+ .ReturnsAsync(new AgentResponse([responseMessage]));
+
+ // Act
+ ResponseResult result = await mockAgent.Object.RunAsync(responseItemMessages, mockThread.Object, options, cancellationToken);
+
+ // Assert
+ mockAgent.Protected()
+ .Verify("RunCoreAsync",
+ Times.Once(),
+ ItExpr.IsAny>(),
+ mockThread.Object,
+ options,
+ cancellationToken
+ );
+
+ Assert.NotNull(result);
+ }
+
+ ///
+ /// Verify that RunStreamingAsync with ResponseItem throws ArgumentNullException when agent is null.
+ ///
+ [Fact]
+ public void RunStreamingAsync_ResponseItem_WithNullAgent_ThrowsArgumentNullException()
+ {
+ // Arrange
+ AIAgent? agent = null;
+ IEnumerable messages = [ResponseItem.CreateUserMessageItem("Test message")];
+
+ // Act & Assert
+ Assert.Throws(
+ "agent",
+ () => agent!.RunStreamingAsync(messages));
+ }
+
+ ///
+ /// Verify that RunStreamingAsync with ResponseItem throws ArgumentNullException when messages is null.
+ ///
+ [Fact]
+ public void RunStreamingAsync_ResponseItem_WithNullMessages_ThrowsArgumentNullException()
+ {
+ // Arrange
+ var mockAgent = new Mock();
+ IEnumerable? messages = null;
+
+ // Act & Assert
+ var exception = Assert.Throws(
+ () => mockAgent.Object.RunStreamingAsync(messages!));
+
+ Assert.Equal("messages", exception.ParamName);
+ }
+
+ ///
+ /// Verify that the RunStreamingAsync with ResponseItem extension method calls the underlying agent's RunStreamingAsync with converted messages and parameters.
+ ///
+ [Fact]
+ public async Task RunStreamingAsync_ResponseItem_CallsUnderlyingAgentAsync()
+ {
+ // Arrange
+ var mockAgent = new Mock();
+ var mockThread = new Mock();
+ var options = new AgentRunOptions();
+ var cancellationToken = new CancellationToken(false);
+ const string TestMessageText = "Hello, assistant!";
+ const string ResponseText1 = "This is ";
+ const string ResponseText2 = "the assistant's response.";
+ IEnumerable responseItemMessages = [ResponseItem.CreateUserMessageItem(TestMessageText)];
+
+ var responseUpdates = new List
+ {
+ new(ChatRole.Assistant, ResponseText1),
+ new(ChatRole.Assistant, ResponseText2)
+ };
+
+ mockAgent
+ .Protected()
+ .Setup>("RunCoreStreamingAsync",
+ ItExpr.IsAny>(),
+ ItExpr.IsAny(),
+ ItExpr.IsAny(),
+ ItExpr.IsAny())
+ .Returns(ToAsyncEnumerableAsync(responseUpdates));
+
+ // Act
+ var result = mockAgent.Object.RunStreamingAsync(responseItemMessages, mockThread.Object, options, cancellationToken);
+ var updateCount = 0;
+ await foreach (var update in result)
+ {
+ updateCount++;
+ }
+
+ // Assert
+ mockAgent.Protected()
+ .Verify("RunCoreStreamingAsync",
+ Times.Once(),
+ ItExpr.IsAny>(),
+ mockThread.Object,
+ options,
+ cancellationToken
+ );
+
+ // The updates are filtered based on raw representation, so we just need to verify the method was called
+ Assert.True(true, "Method was called successfully");
+ }
+
+ #endregion
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
new file mode 100644
index 0000000000..1cc16b95fc
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
@@ -0,0 +1,145 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.Extensions.AI;
+using OpenAI.Chat;
+using ChatMessage = Microsoft.Extensions.AI.ChatMessage;
+using ChatRole = Microsoft.Extensions.AI.ChatRole;
+using TextContent = Microsoft.Extensions.AI.TextContent;
+
+namespace Microsoft.Agents.AI.OpenAI.UnitTests.Extensions;
+
+///
+/// Unit tests for the AgentResponseExtensions class that provides OpenAI extension methods.
+///
+public sealed class AgentResponseExtensionsTests
+{
+ ///
+ /// Verify that AsOpenAIChatCompletion throws ArgumentNullException when response is null.
+ ///
+ [Fact]
+ public void AsOpenAIChatCompletion_WithNullResponse_ThrowsArgumentNullException()
+ {
+ // Arrange
+ AgentResponse? response = null;
+
+ // Act & Assert
+ var exception = Assert.Throws(
+ () => response!.AsOpenAIChatCompletion());
+
+ Assert.Equal("response", exception.ParamName);
+ }
+
+ ///
+ /// Verify that AsOpenAIChatCompletion returns the RawRepresentation when it is a ChatCompletion.
+ ///
+ [Fact]
+ public void AsOpenAIChatCompletion_WithChatCompletionRawRepresentation_ReturnsChatCompletion()
+ {
+ // Arrange
+ ChatCompletion chatCompletion = ModelReaderWriterHelper.CreateChatCompletion("assistant_id", "Hello");
+ var responseMessage = new ChatMessage(ChatRole.Assistant, [new TextContent("Hello")]);
+ var agentResponse = new AgentResponse([responseMessage])
+ {
+ RawRepresentation = chatCompletion
+ };
+
+ // Act
+ ChatCompletion result = agentResponse.AsOpenAIChatCompletion();
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Same(chatCompletion, result);
+ }
+
+ ///
+ /// Verify that AsOpenAIChatCompletion converts a ChatResponse when RawRepresentation is not a ChatCompletion.
+ ///
+ [Fact]
+ public void AsOpenAIChatCompletion_WithNonChatCompletionRawRepresentation_ConvertsChatResponse()
+ {
+ // Arrange
+ const string ResponseText = "This is a test response.";
+ var responseMessage = new ChatMessage(ChatRole.Assistant, [new TextContent(ResponseText)]);
+ var agentResponse = new AgentResponse([responseMessage]);
+
+ // Act
+ ChatCompletion result = agentResponse.AsOpenAIChatCompletion();
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Single(result.Content);
+ Assert.Equal(ResponseText, result.Content[0].Text);
+ }
+
+ ///
+ /// Verify that AsOpenAIResponse throws ArgumentNullException when response is null.
+ ///
+ [Fact]
+ public void AsOpenAIResponse_WithNullResponse_ThrowsArgumentNullException()
+ {
+ // Arrange
+ AgentResponse? response = null;
+
+ // Act & Assert
+ var exception = Assert.Throws(
+ () => response!.AsOpenAIResponse());
+
+ Assert.Equal("response", exception.ParamName);
+ }
+
+ ///
+ /// Verify that AsOpenAIResponse converts a ChatResponse when RawRepresentation is not a ResponseResult.
+ ///
+ [Fact]
+ public void AsOpenAIResponse_WithNonResponseResultRawRepresentation_ConvertsChatResponse()
+ {
+ // Arrange
+ const string ResponseText = "This is a test response.";
+ var responseMessage = new ChatMessage(ChatRole.Assistant, [new TextContent(ResponseText)]);
+ var agentResponse = new AgentResponse([responseMessage]);
+
+ // Act
+ var result = agentResponse.AsOpenAIResponse();
+
+ // Assert
+ Assert.NotNull(result);
+ }
+}
+
+///
+/// Helper class for creating OpenAI model objects using ModelReaderWriter.
+///
+internal static class ModelReaderWriterHelper
+{
+ public static ChatCompletion CreateChatCompletion(string id, string contentText)
+ {
+ string json = $$"""
+ {
+ "id": "{{id}}",
+ "object": "chat.completion",
+ "created": 1700000000,
+ "model": "gpt-4",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "{{contentText}}"
+ },
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 10,
+ "completion_tokens": 10,
+ "total_tokens": 20
+ }
+ }
+ """;
+
+ return System.ClientModel.Primitives.ModelReaderWriter.Read(BinaryData.FromString(json))!;
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
index 2401790dd0..17eb6c94de 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
@@ -569,6 +569,388 @@ public async Task CreateAIAgentAsync_WithClientFactoryAndServices_AppliesBothCor
return property?.GetValue(client) as IServiceProvider;
}
+ ///
+ /// Verify that CreateAIAgentAsync with HostedCodeInterpreterTool properly adds CodeInterpreter tool definition.
+ ///
+ [Fact]
+ public async Task CreateAIAgentAsync_WithHostedCodeInterpreterTool_CreatesAgentWithToolAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string ModelId = "test-model";
+ var options = new ChatClientAgentOptions
+ {
+ Name = "Test Agent",
+ ChatOptions = new ChatOptions
+ {
+ Instructions = "Test instructions",
+ Tools = [new HostedCodeInterpreterTool()]
+ }
+ };
+
+ // Act
+ var agent = await assistantClient.CreateAIAgentAsync(ModelId, options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that CreateAIAgentAsync with HostedCodeInterpreterTool with HostedFileContent input properly creates agent.
+ ///
+ [Fact]
+ public async Task CreateAIAgentAsync_WithHostedCodeInterpreterToolAndHostedFileContent_CreatesAgentWithToolResourcesAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string ModelId = "test-model";
+ var codeInterpreterTool = new HostedCodeInterpreterTool
+ {
+ Inputs = [new HostedFileContent("test-file-id")]
+ };
+ var options = new ChatClientAgentOptions
+ {
+ Name = "Test Agent",
+ ChatOptions = new ChatOptions
+ {
+ Instructions = "Test instructions",
+ Tools = [codeInterpreterTool]
+ }
+ };
+
+ // Act
+ var agent = await assistantClient.CreateAIAgentAsync(ModelId, options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that CreateAIAgentAsync with HostedFileSearchTool properly adds FileSearch tool definition.
+ ///
+ [Fact]
+ public async Task CreateAIAgentAsync_WithHostedFileSearchTool_CreatesAgentWithToolAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string ModelId = "test-model";
+ var options = new ChatClientAgentOptions
+ {
+ Name = "Test Agent",
+ ChatOptions = new ChatOptions
+ {
+ Instructions = "Test instructions",
+ Tools = [new HostedFileSearchTool()]
+ }
+ };
+
+ // Act
+ var agent = await assistantClient.CreateAIAgentAsync(ModelId, options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that CreateAIAgentAsync with HostedFileSearchTool with HostedVectorStoreContent input properly creates agent.
+ ///
+ [Fact]
+ public async Task CreateAIAgentAsync_WithHostedFileSearchToolAndHostedVectorStoreContent_CreatesAgentWithToolResourcesAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string ModelId = "test-model";
+ var fileSearchTool = new HostedFileSearchTool
+ {
+ MaximumResultCount = 10,
+ Inputs = [new HostedVectorStoreContent("test-vector-store-id")]
+ };
+ var options = new ChatClientAgentOptions
+ {
+ Name = "Test Agent",
+ ChatOptions = new ChatOptions
+ {
+ Instructions = "Test instructions",
+ Tools = [fileSearchTool]
+ }
+ };
+
+ // Act
+ var agent = await assistantClient.CreateAIAgentAsync(ModelId, options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that CreateAIAgentAsync with multiple tools including functions properly creates agent.
+ ///
+ [Fact]
+ public async Task CreateAIAgentAsync_WithMixedTools_CreatesAgentWithAllToolsAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string ModelId = "test-model";
+ var testFunction = AIFunctionFactory.Create(() => "test", "TestFunction", "A test function");
+ var options = new ChatClientAgentOptions
+ {
+ Name = "Test Agent",
+ ChatOptions = new ChatOptions
+ {
+ Instructions = "Test instructions",
+ Tools = [new HostedCodeInterpreterTool(), new HostedFileSearchTool(), testFunction]
+ }
+ };
+
+ // Act
+ var agent = await assistantClient.CreateAIAgentAsync(ModelId, options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that CreateAIAgentAsync with function tools properly categorizes them as other tools.
+ ///
+ [Fact]
+ public async Task CreateAIAgentAsync_WithFunctionTools_CategorizesAsOtherToolsAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string ModelId = "test-model";
+ var testFunction = AIFunctionFactory.Create(() => "test", "TestFunction", "A test function");
+ var options = new ChatClientAgentOptions
+ {
+ Name = "Test Agent",
+ ChatOptions = new ChatOptions
+ {
+ Instructions = "Test instructions",
+ Tools = [testFunction]
+ }
+ };
+
+ // Act
+ var agent = await assistantClient.CreateAIAgentAsync(ModelId, options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that AsAIAgent with legacy overload works correctly when assistant instructions are set.
+ ///
+ [Fact]
+ public void AsAIAgent_LegacyOverload_WithAssistantInstructions_SetsInstructions()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ var assistant = ModelReaderWriter.Read(BinaryData.FromString("""{"id": "asst_abc123", "name": "Test Agent", "instructions": "Original Instructions"}"""))!;
+
+ // Act
+ var agent = assistantClient.AsAIAgent(assistant);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ Assert.Equal("Original Instructions", agent.Instructions);
+ }
+
+ ///
+ /// Verify that AsAIAgent with legacy overload works correctly when chatOptions with instructions is provided.
+ ///
+ [Fact]
+ public void AsAIAgent_LegacyOverload_WithChatOptionsInstructions_UsesChatOptionsInstructions()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ var assistant = ModelReaderWriter.Read(BinaryData.FromString("""{"id": "asst_abc123", "name": "Test Agent", "instructions": "Original Instructions"}"""))!;
+ var chatOptions = new ChatOptions { Instructions = "Override Instructions" };
+
+ // Act
+ var agent = assistantClient.AsAIAgent(assistant, chatOptions);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ // The override instructions should be used
+ Assert.Equal("Override Instructions", agent.Instructions);
+ }
+
+ ///
+ /// Verify that AsAIAgent with legacy overload and ClientResult works correctly.
+ ///
+ [Fact]
+ public void AsAIAgent_LegacyOverload_WithClientResult_WorksCorrectly()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ var assistant = ModelReaderWriter.Read(BinaryData.FromString("""{"id": "asst_abc123", "name": "Test Agent", "instructions": "Original Instructions"}"""))!;
+ var clientResult = ClientResult.FromValue(assistant, new FakePipelineResponse());
+
+ // Act
+ var agent = assistantClient.AsAIAgent(clientResult);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Test Agent", agent.Name);
+ }
+
+ ///
+ /// Verify that AsAIAgent with legacy overload throws ArgumentNullException when assistant client is null.
+ ///
+ [Fact]
+ public void AsAIAgent_LegacyOverload_WithNullAssistantClient_ThrowsArgumentNullException()
+ {
+ // Arrange
+ AssistantClient? assistantClient = null;
+ var assistant = ModelReaderWriter.Read(BinaryData.FromString("""{"id": "asst_abc123"}"""))!;
+
+ // Act & Assert
+ var exception = Assert.Throws(() =>
+ assistantClient!.AsAIAgent(assistant));
+
+ Assert.Equal("assistantClient", exception.ParamName);
+ }
+
+ ///
+ /// Verify that AsAIAgent with legacy overload throws ArgumentNullException when assistantMetadata is null.
+ ///
+ [Fact]
+ public void AsAIAgent_LegacyOverload_WithNullAssistantMetadata_ThrowsArgumentNullException()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+
+ // Act & Assert
+ var exception = Assert.Throws(() =>
+ assistantClient.AsAIAgent((Assistant)null!));
+
+ Assert.Equal("assistantMetadata", exception.ParamName);
+ }
+
+ ///
+ /// Verify that AsAIAgent with legacy overload throws ArgumentNullException when clientResult is null.
+ ///
+ [Fact]
+ public void AsAIAgent_LegacyOverload_WithNullClientResult_ThrowsArgumentNullException()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+
+ // Act & Assert
+ var exception = Assert.Throws(() =>
+ assistantClient.AsAIAgent((ClientResult)null!));
+
+ Assert.Equal("assistantClientResult", exception.ParamName);
+ }
+
+ ///
+ /// Verify that GetAIAgentAsync with legacy overload works correctly.
+ ///
+ [Fact]
+ public async Task GetAIAgentAsync_LegacyOverload_WorksCorrectlyAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+ const string AgentId = "asst_abc123";
+
+ // Act
+ var agent = await assistantClient.GetAIAgentAsync(AgentId);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("Original Name", agent.Name);
+ }
+
+ ///
+ /// Verify that GetAIAgentAsync with legacy overload throws ArgumentNullException when assistantClient is null.
+ ///
+ [Fact]
+ public async Task GetAIAgentAsync_LegacyOverload_WithNullAssistantClient_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange
+ AssistantClient? assistantClient = null;
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(() =>
+ assistantClient!.GetAIAgentAsync("asst_abc123"));
+
+ Assert.Equal("assistantClient", exception.ParamName);
+ }
+
+ ///
+ /// Verify that GetAIAgentAsync with legacy overload throws ArgumentException when agentId is empty.
+ ///
+ [Fact]
+ public async Task GetAIAgentAsync_LegacyOverload_WithEmptyAgentId_ThrowsArgumentExceptionAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(() =>
+ assistantClient.GetAIAgentAsync(string.Empty));
+
+ Assert.Equal("agentId", exception.ParamName);
+ }
+
+ ///
+ /// Verify that GetAIAgentAsync with options throws ArgumentNullException when assistantClient is null.
+ ///
+ [Fact]
+ public async Task GetAIAgentAsync_WithOptions_WithNullAssistantClient_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange
+ AssistantClient? assistantClient = null;
+ var options = new ChatClientAgentOptions();
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(() =>
+ assistantClient!.GetAIAgentAsync("asst_abc123", options));
+
+ Assert.Equal("assistantClient", exception.ParamName);
+ }
+
+ ///
+ /// Verify that GetAIAgentAsync with options throws ArgumentNullException when options is null.
+ ///
+ [Fact]
+ public async Task GetAIAgentAsync_WithOptions_WithNullOptions_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange
+ var assistantClient = new TestAssistantClient();
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(() =>
+ assistantClient.GetAIAgentAsync("asst_abc123", (ChatClientAgentOptions)null!));
+
+ Assert.Equal("options", exception.ParamName);
+ }
+
+ ///
+ /// Verify that AsAIAgent with options throws ArgumentNullException when assistantClient is null.
+ ///
+ [Fact]
+ public void AsAIAgent_WithOptions_WithNullAssistantClient_ThrowsArgumentNullException()
+ {
+ // Arrange
+ AssistantClient? assistantClient = null;
+ var assistant = ModelReaderWriter.Read(BinaryData.FromString("""{"id": "asst_abc123"}"""))!;
+ var options = new ChatClientAgentOptions();
+
+ // Act & Assert
+ var exception = Assert.Throws(() =>
+ assistantClient!.AsAIAgent(assistant, options));
+
+ Assert.Equal("assistantClient", exception.ParamName);
+ }
+
///
/// Creates a test AssistantClient implementation for testing.
///
From 4f9cad225280db33561eb32209892a3df482cf87 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 22 Jan 2026 00:18:38 +0000
Subject: [PATCH 3/6] Address code review feedback: remove unused using
directives
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
---
.../ChatClient/StreamingUpdatePipelineResponseTests.cs | 5 +++--
.../Extensions/AgentResponseExtensionsTests.cs | 2 --
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
index 19fb034bbd..aac2a5466f 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
@@ -4,6 +4,7 @@
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Threading;
+using System.Threading.Tasks;
namespace Microsoft.Agents.AI.OpenAI.UnitTests.ChatClient;
@@ -120,7 +121,7 @@ public void BufferContent_ThrowsNotSupportedException()
/// Verify that BufferContentAsync throws NotSupportedException.
///
[Fact]
- public async System.Threading.Tasks.Task BufferContentAsync_ThrowsNotSupportedExceptionAsync()
+ public async Task BufferContentAsync_ThrowsNotSupportedExceptionAsync()
{
// Arrange
IAsyncEnumerable updates = CreateTestUpdatesAsync();
@@ -149,6 +150,6 @@ public void Dispose_DoesNotThrow()
private static async IAsyncEnumerable CreateTestUpdatesAsync()
{
yield return new AgentResponseUpdate(Microsoft.Extensions.AI.ChatRole.Assistant, "test");
- await System.Threading.Tasks.Task.CompletedTask;
+ await Task.CompletedTask;
}
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
index 1cc16b95fc..e026d56104 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using OpenAI.Chat;
using ChatMessage = Microsoft.Extensions.AI.ChatMessage;
From 4d4160c7dd63e9817cdcf80be4775f5a0fc489cd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 22 Jan 2026 00:26:31 +0000
Subject: [PATCH 4/6] Fix format issues: file encoding and remove unused using
directives
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
---
.../AsyncStreamingChatCompletionUpdateCollectionResultTests.cs | 3 +--
.../AsyncStreamingResponseUpdateCollectionResultTests.cs | 3 +--
.../ChatClient/StreamingUpdatePipelineResponseTests.cs | 3 +--
.../Extensions/AgentResponseExtensionsTests.cs | 3 +--
.../Extensions/OpenAIAssistantClientExtensionsTests.cs | 2 +-
5 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs
index d682d7e53b..899d329d5b 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResultTests.cs
@@ -1,8 +1,7 @@
-// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Microsoft. All rights reserved.
using System.ClientModel;
using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using OpenAI.Chat;
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
index 6cb6216f5d..1ef28ad041 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
@@ -1,9 +1,8 @@
-// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Microsoft. All rights reserved.
using System;
using System.ClientModel;
using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using OpenAI.Responses;
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
index aac2a5466f..893255f8d3 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
@@ -1,9 +1,8 @@
-// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Microsoft. All rights reserved.
using System;
using System.ClientModel.Primitives;
using System.Collections.Generic;
-using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Agents.AI.OpenAI.UnitTests.ChatClient;
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
index e026d56104..b2b0a99002 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AgentResponseExtensionsTests.cs
@@ -1,7 +1,6 @@
-// Copyright (c) Microsoft. All rights reserved.
+// Copyright (c) Microsoft. All rights reserved.
using System;
-using Microsoft.Extensions.AI;
using OpenAI.Chat;
using ChatMessage = Microsoft.Extensions.AI.ChatMessage;
using ChatRole = Microsoft.Extensions.AI.ChatRole;
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
index 17eb6c94de..5f92fef13a 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
@@ -845,7 +845,7 @@ public void AsAIAgent_LegacyOverload_WithNullClientResult_ThrowsArgumentNullExce
// Act & Assert
var exception = Assert.Throws(() =>
- assistantClient.AsAIAgent((ClientResult)null!));
+ assistantClient.AsAIAgent(null!));
Assert.Equal("assistantClientResult", exception.ParamName);
}
From 31fb3abc05b9e3f4f3b24800e6ab613f59334b20 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 22 Jan 2026 00:33:13 +0000
Subject: [PATCH 5/6] Fix redundant cast error by using named parameter
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
---
.../Extensions/OpenAIAssistantClientExtensionsTests.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
index 5f92fef13a..31f4369405 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
@@ -845,7 +845,7 @@ public void AsAIAgent_LegacyOverload_WithNullClientResult_ThrowsArgumentNullExce
// Act & Assert
var exception = Assert.Throws(() =>
- assistantClient.AsAIAgent(null!));
+ assistantClient.AsAIAgent(null!, chatOptions: null));
Assert.Equal("assistantClientResult", exception.ParamName);
}
From 3038575aae8a2189926efec919e9d784c2309607 Mon Sep 17 00:00:00 2001
From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com>
Date: Thu, 22 Jan 2026 16:10:32 +0000
Subject: [PATCH 6/6] Remove excessive inline comments per PR review feedback
---
.../AsyncStreamingResponseUpdateCollectionResultTests.cs | 4 ++--
.../ChatClient/StreamingUpdatePipelineResponseTests.cs | 4 ++--
.../Extensions/AIAgentWithOpenAIExtensionsTests.cs | 3 ---
.../Extensions/OpenAIAssistantClientExtensionsTests.cs | 1 -
4 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
index 1ef28ad041..d6bb87596c 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/AsyncStreamingResponseUpdateCollectionResultTests.cs
@@ -116,7 +116,7 @@ public async Task IterateCollection_WithNonStreamingResponseUpdateRawRepresentat
results.Add(update);
}
- // Assert - should be empty since updates don't have StreamingResponseUpdate as RawRepresentation
+ // Assert
Assert.Empty(results);
}
@@ -138,7 +138,7 @@ public async Task IterateCollection_WithChatResponseUpdateWithoutStreamingRespon
results.Add(update);
}
- // Assert - should be empty since the ChatResponseUpdate doesn't have StreamingResponseUpdate as RawRepresentation
+ // Assert
Assert.Empty(results);
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
index 893255f8d3..866bba5700 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/ChatClient/StreamingUpdatePipelineResponseTests.cs
@@ -77,7 +77,7 @@ public void ContentStream_Set_IsNoOp()
// Act
response.ContentStream = testStream;
- // Assert - should remain null
+ // Assert
Assert.Null(response.ContentStream);
testStream.Dispose();
@@ -142,7 +142,7 @@ public void Dispose_DoesNotThrow()
IAsyncEnumerable updates = CreateTestUpdatesAsync();
PipelineResponse response = new StreamingUpdatePipelineResponse(updates);
- // Act & Assert - should not throw
+ // Act & Assert
response.Dispose();
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs
index a3cd7cd541..db22ab090b 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/AIAgentWithOpenAIExtensionsTests.cs
@@ -369,9 +369,6 @@ public async Task RunStreamingAsync_ResponseItem_CallsUnderlyingAgentAsync()
options,
cancellationToken
);
-
- // The updates are filtered based on raw representation, so we just need to verify the method was called
- Assert.True(true, "Method was called successfully");
}
#endregion
diff --git a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
index 31f4369405..44a4b73b52 100644
--- a/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Extensions/OpenAIAssistantClientExtensionsTests.cs
@@ -778,7 +778,6 @@ public void AsAIAgent_LegacyOverload_WithChatOptionsInstructions_UsesChatOptions
// Assert
Assert.NotNull(agent);
Assert.Equal("Test Agent", agent.Name);
- // The override instructions should be used
Assert.Equal("Override Instructions", agent.Instructions);
}