.NET: Improve unit test coverage for Microsoft.Agents.AI.Abstractions (#3381)

* Initial plan

* Add unit tests to improve coverage for Microsoft.Agents.AI.Abstractions

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Fix file encoding and naming rule violation in new test files

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Remove ChatMessageStoreExtensionsTests.cs to avoid duplication with Wesley's work

Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>

* Fix AgentThread to AgentSession rename in unit tests

Update MockAgentWithName in AIAgentTests.cs and DelegatingAIAgentTests.cs
to use the renamed AgentSession class and corresponding methods:
- AgentThread -> AgentSession
- GetNewThreadAsync -> GetNewSessionAsync
- DeserializeThreadAsync -> DeserializeSessionAsync
- thread parameter -> session parameter

* Fix: Rename GetNewSessionAsync to CreateSessionAsync to match API changes

* Fix: Add SerializeSession override and remove async from DeserializeSessionAsync

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rogerbarreto <19890735+rogerbarreto@users.noreply.github.com>
This commit is contained in:
Copilot
2026-02-04 17:43:31 +00:00
committed by GitHub
Unverified
parent 6255abd687
commit e8902c0d11
9 changed files with 713 additions and 0 deletions
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Agents.AI.Abstractions.UnitTests;
/// <summary>
/// Unit tests for the <see cref="AIAgentMetadata"/> class.
/// </summary>
public class AIAgentMetadataTests
{
[Fact]
public void Constructor_WithNoArguments_SetsProviderNameToNull()
{
// Arrange & Act
AIAgentMetadata metadata = new();
// Assert
Assert.Null(metadata.ProviderName);
}
[Fact]
public void Constructor_WithProviderName_SetsProperty()
{
// Arrange
const string ProviderName = "TestProvider";
// Act
AIAgentMetadata metadata = new(ProviderName);
// Assert
Assert.Equal(ProviderName, metadata.ProviderName);
}
[Fact]
public void Constructor_WithNullProviderName_SetsProviderNameToNull()
{
// Arrange & Act
AIAgentMetadata metadata = new(null);
// Assert
Assert.Null(metadata.ProviderName);
}
}
@@ -364,6 +364,74 @@ public class AIAgentTests
#endregion
#region Name and Description Property Tests
/// <summary>
/// Verify that Name property returns the value from the derived class.
/// </summary>
[Fact]
public void Name_ReturnsValueFromDerivedClass()
{
// Arrange
var agent = new MockAgentWithName("TestAgentName", "TestAgentDescription");
// Act
string? name = agent.Name;
// Assert
Assert.Equal("TestAgentName", name);
}
/// <summary>
/// Verify that Description property returns the value from the derived class.
/// </summary>
[Fact]
public void Description_ReturnsValueFromDerivedClass()
{
// Arrange
var agent = new MockAgentWithName("TestAgentName", "TestAgentDescription");
// Act
string? description = agent.Description;
// Assert
Assert.Equal("TestAgentDescription", description);
}
/// <summary>
/// Verify that Name property returns null when not overridden.
/// </summary>
[Fact]
public void Name_ReturnsNullByDefault()
{
// Arrange
var agent = new MockAgent();
// Act
string? name = agent.Name;
// Assert
Assert.Null(name);
}
/// <summary>
/// Verify that Description property returns null when not overridden.
/// </summary>
[Fact]
public void Description_ReturnsNullByDefault()
{
// Arrange
var agent = new MockAgent();
// Act
string? description = agent.Description;
// Assert
Assert.Null(description);
}
#endregion
/// <summary>
/// Typed mock session.
/// </summary>
@@ -402,6 +470,44 @@ public class AIAgentTests
throw new NotImplementedException();
}
private sealed class MockAgentWithName : AIAgent
{
private readonly string? _name;
private readonly string? _description;
public MockAgentWithName(string? name, string? description)
{
this._name = name;
this._description = description;
}
public override string? Name => this._name;
public override string? Description => this._description;
public override ValueTask<AgentSession> CreateSessionAsync(CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public override ValueTask<AgentSession> DeserializeSessionAsync(JsonElement serializedSession, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
=> throw new NotImplementedException();
public override JsonElement SerializeSession(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null)
=> throw new NotImplementedException();
protected override Task<AgentResponse> RunCoreAsync(
IEnumerable<ChatMessage> messages,
AgentSession? session = null,
AgentRunOptions? options = null,
CancellationToken cancellationToken = default) =>
throw new NotImplementedException();
protected override IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
IEnumerable<ChatMessage> messages,
AgentSession? session = null,
AgentRunOptions? options = null,
CancellationToken cancellationToken = default) =>
throw new NotImplementedException();
}
private static async IAsyncEnumerable<T> ToAsyncEnumerableAsync<T>(IEnumerable<T> values)
{
await Task.Yield();
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
@@ -155,6 +156,111 @@ public class AIContextProviderTests
#endregion
#region InvokingContext Tests
[Fact]
public void InvokingContext_RequestMessages_SetterThrowsForNull()
{
// Arrange
var messages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var context = new AIContextProvider.InvokingContext(messages);
// Act & Assert
Assert.Throws<ArgumentNullException>(() => context.RequestMessages = null!);
}
[Fact]
public void InvokingContext_RequestMessages_SetterRoundtrips()
{
// Arrange
var initialMessages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var newMessages = new List<ChatMessage> { new(ChatRole.User, "New message") };
var context = new AIContextProvider.InvokingContext(initialMessages);
// Act
context.RequestMessages = newMessages;
// Assert
Assert.Same(newMessages, context.RequestMessages);
}
#endregion
#region InvokedContext Tests
[Fact]
public void InvokedContext_RequestMessages_SetterThrowsForNull()
{
// Arrange
var messages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var context = new AIContextProvider.InvokedContext(messages, aiContextProviderMessages: null);
// Act & Assert
Assert.Throws<ArgumentNullException>(() => context.RequestMessages = null!);
}
[Fact]
public void InvokedContext_RequestMessages_SetterRoundtrips()
{
// Arrange
var initialMessages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var newMessages = new List<ChatMessage> { new(ChatRole.User, "New message") };
var context = new AIContextProvider.InvokedContext(initialMessages, aiContextProviderMessages: null);
// Act
context.RequestMessages = newMessages;
// Assert
Assert.Same(newMessages, context.RequestMessages);
}
[Fact]
public void InvokedContext_AIContextProviderMessages_Roundtrips()
{
// Arrange
var requestMessages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var aiContextMessages = new List<ChatMessage> { new(ChatRole.System, "AI context message") };
var context = new AIContextProvider.InvokedContext(requestMessages, aiContextProviderMessages: null);
// Act
context.AIContextProviderMessages = aiContextMessages;
// Assert
Assert.Same(aiContextMessages, context.AIContextProviderMessages);
}
[Fact]
public void InvokedContext_ResponseMessages_Roundtrips()
{
// Arrange
var requestMessages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var responseMessages = new List<ChatMessage> { new(ChatRole.Assistant, "Response message") };
var context = new AIContextProvider.InvokedContext(requestMessages, aiContextProviderMessages: null);
// Act
context.ResponseMessages = responseMessages;
// Assert
Assert.Same(responseMessages, context.ResponseMessages);
}
[Fact]
public void InvokedContext_InvokeException_Roundtrips()
{
// Arrange
var requestMessages = new ReadOnlyCollection<ChatMessage>([new(ChatRole.User, "Hello")]);
var exception = new InvalidOperationException("Test exception");
var context = new AIContextProvider.InvokedContext(requestMessages, aiContextProviderMessages: null);
// Act
context.InvokeException = exception;
// Assert
Assert.Same(exception, context.InvokeException);
}
#endregion
private sealed class TestAIContextProvider : AIContextProvider
{
public override ValueTask<AIContext> InvokingAsync(InvokingContext context, CancellationToken cancellationToken = default)
@@ -346,4 +346,91 @@ public class AgentResponseTests
// Act & Assert.
Assert.False(response.TryDeserialize<Animal>(TestJsonSerializerContext.Default.Options, out _));
}
[Fact]
public void UserInputRequests_ReturnsEmptyWhenNoMessages()
{
// Arrange
AgentResponse response = new();
// Act
IEnumerable<UserInputRequestContent> requests = response.UserInputRequests;
// Assert
Assert.Empty(requests);
}
[Fact]
public void UserInputRequests_ReturnsEmptyWhenNoUserInputRequestContent()
{
// Arrange
AgentResponse response = new(new ChatMessage(ChatRole.Assistant, "Hello"));
// Act
IEnumerable<UserInputRequestContent> requests = response.UserInputRequests;
// Assert
Assert.Empty(requests);
}
[Fact]
public void ToAgentResponseUpdatesWithNoMessagesProducesEmptyArray()
{
// Arrange
AgentResponse response = new();
// Act
AgentResponseUpdate[] updates = response.ToAgentResponseUpdates();
// Assert
Assert.Empty(updates);
}
[Fact]
public void ToAgentResponseUpdatesWithUsageOnlyProducesSingleUpdate()
{
// Arrange
AgentResponse response = new()
{
Usage = new UsageDetails { TotalTokenCount = 100 }
};
// Act
AgentResponseUpdate[] updates = response.ToAgentResponseUpdates();
// Assert
AgentResponseUpdate update = Assert.Single(updates);
UsageContent usageContent = Assert.IsType<UsageContent>(update.Contents[0]);
Assert.Equal(100, usageContent.Details.TotalTokenCount);
}
[Fact]
public void ToAgentResponseUpdatesWithAdditionalPropertiesOnlyProducesSingleUpdate()
{
// Arrange
AgentResponse response = new()
{
AdditionalProperties = new() { ["key"] = "value" }
};
// Act
AgentResponseUpdate[] updates = response.ToAgentResponseUpdates();
// Assert
AgentResponseUpdate update = Assert.Single(updates);
Assert.NotNull(update.AdditionalProperties);
Assert.Equal("value", update.AdditionalProperties!["key"]);
}
[Fact]
public void Deserialize_ThrowsWhenDeserializationReturnsNull()
{
// Arrange
AgentResponse response = new(new ChatMessage(ChatRole.Assistant, "null"));
// Act & Assert
InvalidOperationException exception = Assert.Throws<InvalidOperationException>(
() => response.Deserialize<Animal>(TestJsonSerializerContext.Default.Options));
Assert.Equal("The deserialized response is null.", exception.Message);
}
}
@@ -299,6 +299,161 @@ public class AgentResponseUpdateExtensionsTests
Assert.Equal(expected, response.CreatedAt);
}
#region AsChatResponse Tests
[Fact]
public void AsChatResponse_WithNullArgument_ThrowsArgumentNullException()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>("response", () => ((AgentResponse)null!).AsChatResponse());
}
[Fact]
public void AsChatResponse_WithRawRepresentationAsChatResponse_ReturnsSameInstance()
{
// Arrange
ChatResponse originalChatResponse = new()
{
ResponseId = "original-response",
Messages = [new ChatMessage(ChatRole.Assistant, "Hello")]
};
AgentResponse agentResponse = new(originalChatResponse);
// Act
ChatResponse result = agentResponse.AsChatResponse();
// Assert
Assert.Same(originalChatResponse, result);
}
[Fact]
public void AsChatResponse_WithoutRawRepresentation_CreatesNewChatResponse()
{
// Arrange
AgentResponse agentResponse = new(new ChatMessage(ChatRole.Assistant, "Test message"))
{
ResponseId = "test-response-id",
CreatedAt = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero),
Usage = new UsageDetails { TotalTokenCount = 50 },
AdditionalProperties = new() { ["key"] = "value" },
ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
};
// Act
ChatResponse result = agentResponse.AsChatResponse();
// Assert
Assert.NotNull(result);
Assert.Equal("test-response-id", result.ResponseId);
Assert.Equal(new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero), result.CreatedAt);
Assert.Same(agentResponse.Messages, result.Messages);
Assert.Same(agentResponse, result.RawRepresentation);
Assert.Same(agentResponse.Usage, result.Usage);
Assert.Same(agentResponse.AdditionalProperties, result.AdditionalProperties);
Assert.Equal(agentResponse.ContinuationToken, result.ContinuationToken);
}
#endregion
#region AsChatResponseUpdate Tests
[Fact]
public void AsChatResponseUpdate_WithNullArgument_ThrowsArgumentNullException()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>("responseUpdate", () => ((AgentResponseUpdate)null!).AsChatResponseUpdate());
}
[Fact]
public void AsChatResponseUpdate_WithRawRepresentationAsChatResponseUpdate_ReturnsSameInstance()
{
// Arrange
ChatResponseUpdate originalChatResponseUpdate = new()
{
ResponseId = "original-update",
Contents = [new TextContent("Hello")]
};
AgentResponseUpdate agentResponseUpdate = new(originalChatResponseUpdate);
// Act
ChatResponseUpdate result = agentResponseUpdate.AsChatResponseUpdate();
// Assert
Assert.Same(originalChatResponseUpdate, result);
}
[Fact]
public void AsChatResponseUpdate_WithoutRawRepresentation_CreatesNewChatResponseUpdate()
{
// Arrange
AgentResponseUpdate agentResponseUpdate = new(ChatRole.Assistant, "Test")
{
AuthorName = "TestAuthor",
ResponseId = "update-id",
MessageId = "message-id",
CreatedAt = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero),
AdditionalProperties = new() { ["key"] = "value" },
ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
};
// Act
ChatResponseUpdate result = agentResponseUpdate.AsChatResponseUpdate();
// Assert
Assert.NotNull(result);
Assert.Equal("TestAuthor", result.AuthorName);
Assert.Equal("update-id", result.ResponseId);
Assert.Equal("message-id", result.MessageId);
Assert.Equal(new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero), result.CreatedAt);
Assert.Equal(ChatRole.Assistant, result.Role);
Assert.Same(agentResponseUpdate.Contents, result.Contents);
Assert.Same(agentResponseUpdate, result.RawRepresentation);
Assert.Same(agentResponseUpdate.AdditionalProperties, result.AdditionalProperties);
Assert.Equal(agentResponseUpdate.ContinuationToken, result.ContinuationToken);
}
#endregion
#region AsChatResponseUpdatesAsync Tests
[Fact]
public async Task AsChatResponseUpdatesAsync_WithNullArgument_ThrowsArgumentNullExceptionAsync()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ArgumentNullException>("responseUpdates", async () =>
{
await foreach (ChatResponseUpdate _ in ((IAsyncEnumerable<AgentResponseUpdate>)null!).AsChatResponseUpdatesAsync())
{
// Do nothing
}
});
}
[Fact]
public async Task AsChatResponseUpdatesAsync_ConvertsUpdatesAsync()
{
// Arrange
AgentResponseUpdate[] updates =
[
new(ChatRole.Assistant, "First"),
new(ChatRole.Assistant, "Second"),
];
// Act
List<ChatResponseUpdate> results = [];
await foreach (ChatResponseUpdate update in YieldAsync(updates).AsChatResponseUpdatesAsync())
{
results.Add(update);
}
// Assert
Assert.Equal(2, results.Count);
Assert.Equal("First", Assert.IsType<TextContent>(results[0].Contents[0]).Text);
Assert.Equal("Second", Assert.IsType<TextContent>(results[1].Contents[0]).Text);
}
#endregion
private static async IAsyncEnumerable<AgentResponseUpdate> YieldAsync(IEnumerable<AgentResponseUpdate> updates)
{
foreach (AgentResponseUpdate update in updates)
@@ -199,4 +199,30 @@ public class AgentResponseUpdateTests
Assert.NotNull(result.ContinuationToken);
Assert.Equivalent(ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }), result.ContinuationToken);
}
[Fact]
public void UserInputRequests_ReturnsEmptyWhenNoContents()
{
// Arrange
AgentResponseUpdate update = new();
// Act
IEnumerable<UserInputRequestContent> requests = update.UserInputRequests;
// Assert
Assert.Empty(requests);
}
[Fact]
public void UserInputRequests_ReturnsEmptyWhenNoUserInputRequestContent()
{
// Arrange
AgentResponseUpdate update = new(ChatRole.Assistant, "Hello");
// Act
IEnumerable<UserInputRequestContent> requests = update.UserInputRequests;
// Assert
Assert.Empty(requests);
}
}
@@ -76,6 +76,140 @@ public class ChatHistoryProviderTests
#endregion
#region InvokingContext Tests
[Fact]
public void InvokingContext_Constructor_ThrowsForNullMessages()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>(() => new ChatHistoryProvider.InvokingContext(null!));
}
[Fact]
public void InvokingContext_RequestMessages_SetterThrowsForNull()
{
// Arrange
var messages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var context = new ChatHistoryProvider.InvokingContext(messages);
// Act & Assert
Assert.Throws<ArgumentNullException>(() => context.RequestMessages = null!);
}
[Fact]
public void InvokingContext_RequestMessages_SetterRoundtrips()
{
// Arrange
var initialMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var newMessages = new List<ChatMessage> { new(ChatRole.User, "New message") };
var context = new ChatHistoryProvider.InvokingContext(initialMessages);
// Act
context.RequestMessages = newMessages;
// Assert
Assert.Same(newMessages, context.RequestMessages);
}
#endregion
#region InvokedContext Tests
[Fact]
public void InvokedContext_Constructor_ThrowsForNullRequestMessages()
{
// Arrange & Act & Assert
Assert.Throws<ArgumentNullException>(() => new ChatHistoryProvider.InvokedContext(null!, []));
}
[Fact]
public void InvokedContext_RequestMessages_SetterThrowsForNull()
{
// Arrange
var requestMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
// Act & Assert
Assert.Throws<ArgumentNullException>(() => context.RequestMessages = null!);
}
[Fact]
public void InvokedContext_RequestMessages_SetterRoundtrips()
{
// Arrange
var initialMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var newMessages = new List<ChatMessage> { new(ChatRole.User, "New message") };
var context = new ChatHistoryProvider.InvokedContext(initialMessages, []);
// Act
context.RequestMessages = newMessages;
// Assert
Assert.Same(newMessages, context.RequestMessages);
}
[Fact]
public void InvokedContext_ChatHistoryProviderMessages_SetterRoundtrips()
{
// Arrange
var requestMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var newProviderMessages = new List<ChatMessage> { new(ChatRole.System, "System message") };
var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
// Act
context.ChatHistoryProviderMessages = newProviderMessages;
// Assert
Assert.Same(newProviderMessages, context.ChatHistoryProviderMessages);
}
[Fact]
public void InvokedContext_AIContextProviderMessages_Roundtrips()
{
// Arrange
var requestMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var aiContextMessages = new List<ChatMessage> { new(ChatRole.System, "AI context message") };
var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
// Act
context.AIContextProviderMessages = aiContextMessages;
// Assert
Assert.Same(aiContextMessages, context.AIContextProviderMessages);
}
[Fact]
public void InvokedContext_ResponseMessages_Roundtrips()
{
// Arrange
var requestMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var responseMessages = new List<ChatMessage> { new(ChatRole.Assistant, "Response message") };
var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
// Act
context.ResponseMessages = responseMessages;
// Assert
Assert.Same(responseMessages, context.ResponseMessages);
}
[Fact]
public void InvokedContext_InvokeException_Roundtrips()
{
// Arrange
var requestMessages = new List<ChatMessage> { new(ChatRole.User, "Hello") };
var exception = new InvalidOperationException("Test exception");
var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
// Act
context.InvokeException = exception;
// Assert
Assert.Same(exception, context.InvokeException);
}
#endregion
private sealed class TestChatHistoryProvider : ChatHistoryProvider
{
public override ValueTask<IEnumerable<ChatMessage>> InvokingAsync(InvokingContext context, CancellationToken cancellationToken = default)
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
@@ -145,6 +146,26 @@ public class DelegatingAIAgentTests
this._innerAgentMock.Verify(x => x.CreateSessionAsync(), Times.Once);
}
/// <summary>
/// Verify that DeserializeSessionAsync delegates to inner agent.
/// </summary>
[Fact]
public async Task DeserializeSessionAsync_DelegatesToInnerAgentAsync()
{
// Arrange
var serializedSession = JsonSerializer.SerializeToElement("test-session-id", TestJsonSerializerContext.Default.String);
this._innerAgentMock
.Setup(x => x.DeserializeSessionAsync(It.IsAny<JsonElement>(), null, It.IsAny<CancellationToken>()))
.ReturnsAsync(this._testSession);
// Act
var session = await this._delegatingAgent.DeserializeSessionAsync(serializedSession);
// Assert
Assert.Same(this._testSession, session);
this._innerAgentMock.Verify(x => x.DeserializeSessionAsync(It.IsAny<JsonElement>(), null, It.IsAny<CancellationToken>()), Times.Once);
}
/// <summary>
/// Verify that RunAsync delegates to inner agent with correct parameters.
/// </summary>
@@ -614,6 +614,42 @@ public class InMemoryChatHistoryProviderTests
reducerMock.Verify(r => r.ReduceAsync(It.IsAny<IEnumerable<ChatMessage>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
public async Task InvokedAsync_WithException_DoesNotAddMessagesAsync()
{
// Arrange
var provider = new InMemoryChatHistoryProvider();
var requestMessages = new List<ChatMessage>
{
new(ChatRole.User, "Hello")
};
var responseMessages = new List<ChatMessage>
{
new(ChatRole.Assistant, "Hi there!")
};
var context = new ChatHistoryProvider.InvokedContext(requestMessages, [])
{
ResponseMessages = responseMessages,
InvokeException = new InvalidOperationException("Test exception")
};
// Act
await provider.InvokedAsync(context, CancellationToken.None);
// Assert
Assert.Empty(provider);
}
[Fact]
public async Task InvokingAsync_WithNullContext_ThrowsArgumentNullExceptionAsync()
{
// Arrange
var provider = new InMemoryChatHistoryProvider();
// Act & Assert
await Assert.ThrowsAsync<ArgumentNullException>(() => provider.InvokingAsync(null!, CancellationToken.None).AsTask());
}
public class TestAIContent(string testData) : AIContent
{
public string TestData => testData;