Files
agent-framework/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/InMemoryChatMessageStoreTests.cs
T
westey ff3e13c2aa .Net: Add support for 3rd party thread storage and thread serialization (#203)
* Add thread storage and serialization POC

* Switch to using JsonElement and add unit tests

* Add additional unit tests.

* Exclude private debugger properties from CodeCoverage.

* Rename IChatMessagesStorable to IChatMessageStore

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Improve xml doc.

* Update the message storing thread to always use external store for both local and remote storage.

* Remove threadid from the IChatMessageStore interface, since the store should own the thread id itself, if it requires one.

* Switch GetMessages to IEnumerable

* Address pr comments.

* Make jsonserializer options default consistent on DeserializeThreadAsync

* Move message storing thread functionality into AgentThread and simplify AgentThread behavior.

* Remove embedding generation from VectorStore chat history sample.

* Remove unecessary code and fix formatting.

* Make GetNewThread and DeserializeThread virtual with default implementations.
Remove unsued json utilities.

* Fix formatting

* Remove problem test.

* Add more unit tests

* Remove unused using clause.

* Address pr feedback.

* Address PR comments.

* Make InMemory store internal

* Switch InMemoryChatMessageStore to implement IList instead of inheriting from List.

* Rename store deserialize param.

* Update serialization based on PR comments.

* Remove confusing comment.

* Address Deserialization PR comments in the same way as Serialization

* Add State to IChatMessageStore Serialize and Deserialize names.
Make Thread Deserialize internal.
Make AgentThread type switching fobidden.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
2025-08-05 17:24:25 +00:00

101 lines
2.8 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Extensions.AI.Agents.Abstractions.UnitTests;
/// <summary>
/// Contains tests for the <see cref="InMemoryChatMessageStore"/> class.
/// </summary>
public class InMemoryChatMessageStoreTests
{
[Fact]
public async Task AddMessagesAsyncAddsMessagesAndReturnsNullThreadIdAsync()
{
var store = new InMemoryChatMessageStore();
var messages = new List<ChatMessage>
{
new(ChatRole.User, "Hello"),
new(ChatRole.Assistant, "Hi there!")
};
await store.AddMessagesAsync(messages, CancellationToken.None);
Assert.Equal(2, store.Count);
Assert.Equal("Hello", store[0].Text);
Assert.Equal("Hi there!", store[1].Text);
}
[Fact]
public async Task AddMessagesAsyncWithEmptyDoesNotFailAsync()
{
var store = new InMemoryChatMessageStore();
await store.AddMessagesAsync([], CancellationToken.None);
Assert.Empty(store);
}
[Fact]
public async Task GetMessagesAsyncReturnsAllMessagesAsync()
{
var store = new InMemoryChatMessageStore
{
new ChatMessage(ChatRole.User, "Test1"),
new ChatMessage(ChatRole.Assistant, "Test2")
};
var result = (await store.GetMessagesAsync(CancellationToken.None)).ToList();
Assert.Equal(2, result.Count);
Assert.Contains(result, m => m.Text == "Test1");
Assert.Contains(result, m => m.Text == "Test2");
}
[Fact]
public async Task DeserializeWithEmptyElementAsync()
{
var newStore = new InMemoryChatMessageStore();
var emptyObject = JsonSerializer.Deserialize<JsonElement>("{}");
await newStore.DeserializeStateAsync(emptyObject);
Assert.Empty(newStore);
}
[Fact]
public async Task SerializeAndDeserializeRoundtripsAsync()
{
var store = new InMemoryChatMessageStore
{
new ChatMessage(ChatRole.User, "A"),
new ChatMessage(ChatRole.Assistant, "B")
};
var jsonElement = await store.SerializeStateAsync();
var newStore = new InMemoryChatMessageStore();
await newStore.DeserializeStateAsync(jsonElement);
Assert.Equal(2, newStore.Count);
Assert.Equal("A", newStore[0].Text);
Assert.Equal("B", newStore[1].Text);
}
[Fact]
public async Task AddMessagesAsyncWithEmptyMessagesDoesNotChangeStoreAsync()
{
var store = new InMemoryChatMessageStore();
var messages = new List<ChatMessage>();
await store.AddMessagesAsync(messages, CancellationToken.None);
Assert.Empty(store);
}
}