From 994c8660df392c4ec78a3fae9598b4821c97deb9 Mon Sep 17 00:00:00 2001 From: Griffin Bassman Date: Thu, 30 Jan 2025 16:53:42 -0500 Subject: [PATCH] fix: add unit tests for dotnet and improve test infrastructure (#5269) --- .../AgentTests.cs | 198 +++++------------- .../Microsoft.AutoGen.Core.Tests/TestAgent.cs | 3 +- 2 files changed, 57 insertions(+), 144 deletions(-) diff --git a/dotnet/test/Microsoft.AutoGen.Core.Tests/AgentTests.cs b/dotnet/test/Microsoft.AutoGen.Core.Tests/AgentTests.cs index 11cd42362db..e8cd894f75d 100644 --- a/dotnet/test/Microsoft.AutoGen.Core.Tests/AgentTests.cs +++ b/dotnet/test/Microsoft.AutoGen.Core.Tests/AgentTests.cs @@ -7,49 +7,71 @@ namespace Microsoft.AutoGen.Core.Tests; -//[Collection(ClusterFixtureCollection.Name)] public class AgentTests() { [Fact] - public async Task Agent_ShouldNotReceiveMessages_WhenNotSubscribed() + public async Task AgentShouldNotReceiveMessagesWhenNotSubscribedTest() { var runtime = new InProcessRuntime(); await runtime.StartAsync(); Logger logger = new(new LoggerFactory()); - await runtime.RegisterAgentFactoryAsync("MyAgent", (id, runtime) => ValueTask.FromResult(new TestAgent(id, runtime, logger))); - await runtime.RegisterImplicitAgentSubscriptionsAsync("MyAgent"); + TestAgent agent = null!; - var topicType = "TestTopic"; + await runtime.RegisterAgentFactoryAsync("MyAgent", (id, runtime) => + { + agent = new TestAgent(id, runtime, logger); + return ValueTask.FromResult(agent); + }); + + // Ensure the agent is actually created + AgentId agentId = await runtime.GetAgentAsync("MyAgent", lazy: false); - await runtime.PublishMessageAsync(new TextMessage { Source = topicType, Content = "test" }, new TopicId("TestTopic")).ConfigureAwait(true); + // Validate agent ID + agentId.Should().Be(agent.Id, "Agent ID should match the registered agent"); + var topicType = "TestTopic"; + + await runtime.PublishMessageAsync(new TextMessage { Source = topicType, Content = "test" }, new TopicId(topicType)).ConfigureAwait(true); await runtime.RunUntilIdleAsync(); - TestAgent.ReceivedMessages.Any().Should().BeFalse("Agent should not receive messages when not subscribed."); + agent.ReceivedMessages.Any().Should().BeFalse("Agent should not receive messages when not subscribed."); } [Fact] - public async Task Agent_ShoulReceiveMessages_WhenSubscribed() + public async Task AgentShouldReceiveMessagesWhenSubscribedTest() { var runtime = new InProcessRuntime(); await runtime.StartAsync(); Logger logger = new(new LoggerFactory()); - await runtime.RegisterAgentFactoryAsync("MyAgent", (id, runtime) => ValueTask.FromResult(new SubscribedAgent(id, runtime, logger))); + SubscribedAgent agent = null!; + + await runtime.RegisterAgentFactoryAsync("MyAgent", (id, runtime) => + { + agent = new SubscribedAgent(id, runtime, logger); + return ValueTask.FromResult(agent); + }); + + // Ensure the agent is actually created + AgentId agentId = await runtime.GetAgentAsync("MyAgent", lazy: false); + + // Validate agent ID + agentId.Should().Be(agent.Id, "Agent ID should match the registered agent"); + await runtime.RegisterImplicitAgentSubscriptionsAsync("MyAgent"); var topicType = "TestTopic"; - await runtime.PublishMessageAsync(new TextMessage { Source = topicType, Content = "test" }, new TopicId("TestTopic")).ConfigureAwait(true); + await runtime.PublishMessageAsync(new TextMessage { Source = topicType, Content = "test" }, new TopicId(topicType)).ConfigureAwait(true); await runtime.RunUntilIdleAsync(); - TestAgent.ReceivedMessages.Any().Should().BeTrue("Agent should receive messages when subscribed."); + agent.ReceivedMessages.Any().Should().BeTrue("Agent should receive messages when subscribed."); } [Fact] - public async Task SendMessageAsync_ShouldReturnResponse() + public async Task SendMessageAsyncShouldReturnResponseTest() { // Arrange var runtime = new InProcessRuntime(); @@ -72,43 +94,6 @@ public async Task SendMessageAsync_ShouldReturnResponse() } } - // / - // / Verify that if the agent is not initialized via AgentWorker, it should throw the correct exception. - // / - // / void - // [Fact] - // public async Task Agent_ShouldThrowException_WhenNotInitialized() - // { - // using var fixture = new InMemoryAgentRuntimeFixture(); - // var agent = ActivatorUtilities.CreateInstance(fixture.AppHost.Services); - // await Assert.ThrowsAsync( - // async () => - // { - // await agent.AddSubscriptionAsync("TestEvent"); - // } - // ); - // } - - // /// - // /// validate that the agent is initialized correctly with implicit subs - // /// - // /// void - // [Fact] - // public async Task Agent_ShouldInitializeCorrectly() - // { - // var fixture = new InMemoryAgentRuntimeFixture(); - // var (runtime, agent) = fixture.Start(); - // Assert.Equal(nameof(AgentRuntime), runtime.GetType().Name); - // var subscriptions = await agent.GetSubscriptionsAsync(); - // Assert.Equal(2, subscriptions.Count); - // fixture.Stop(); - // } - /// - /// Test AddSubscriptionAsync method - /// - /// void - /// - public class ReceiverAgent(AgentId id, IAgentRuntime runtime) : BaseAgent(id, runtime, "Receiver Agent", null), IHandle @@ -123,7 +108,7 @@ public ValueTask HandleAsync(string item, MessageContext messageContext) } [Fact] - public async Task SubscribeAsync_UnsubscribeAsync_and_GetSubscriptionsTest() + public async Task SubscribeAsyncRemoveSubscriptionAsyncAndGetSubscriptionsTest() { var runtime = new InProcessRuntime(); await runtime.StartAsync(); @@ -161,97 +146,24 @@ await runtime.RegisterAgentFactoryAsync("MyAgent", (id, runtime) => Assert.True(agent.ReceivedItems.Count == 1); } - // /// - // /// Test StoreAsync and ReadAsync methods - // /// - // /// void - // [Fact] - // public async Task StoreAsync_and_ReadAsyncTest() - // { - // var fixture = new InMemoryAgentRuntimeFixture(); - // var (_, agent) = fixture.Start(); - // Dictionary state = new() - // { - // { "testdata", "Active" } - // }; - // await agent.StoreAsync(new AgentState - // { - // AgentId = agent.AgentId, - // TextData = JsonSerializer.Serialize(state) - // }).ConfigureAwait(true); - // var readState = await agent.ReadAsync(agent.AgentId).ConfigureAwait(true); - // var read = JsonSerializer.Deserialize>(readState.TextData) ?? new Dictionary { { "data", "No state data found" } }; - // read.TryGetValue("testdata", out var value); - // Assert.Equal("Active", value); - // fixture.Stop(); - // } - - // /// - // /// Test PublishMessageAsync method and ReceiveMessage method - // /// - // /// void - // [Fact] - // public async Task PublishMessageAsync_and_ReceiveMessageTest() - // { - // var fixture = new InMemoryAgentRuntimeFixture(); - // var (_, agent) = fixture.Start(); - // var topicType = "TestTopic"; - // await agent.AddSubscriptionAsync(topicType).ConfigureAwait(true); - // var subscriptions = await agent.GetSubscriptionsAsync().ConfigureAwait(true); - // var found = false; - // foreach (var subscription in subscriptions) - // { - // if (subscription.TypeSubscription.TopicType == topicType) - // { - // found = true; - // } - // } - // Assert.True(found); - // await agent.PublishMessageAsync(new TextMessage() - // { - // Source = topicType, - // TextMessage_ = "buffer" - // }, topicType).ConfigureAwait(true); - // await Task.Delay(100); - // Assert.True(TestAgent.ReceivedMessages.ContainsKey(topicType)); - // fixture.Stop(); - // } - - // [Fact] - // public async Task InvokeCorrectHandler() - // { - // var agent = new TestAgent(new AgentsMetadata(TypeRegistry.Empty, new Dictionary(), new Dictionary>(), new Dictionary>()), new Logger(new LoggerFactory())); - // await agent.HandleObjectAsync("hello world"); - // await agent.HandleObjectAsync(42); - // agent.ReceivedItems.Should().HaveCount(2); - // agent.ReceivedItems[0].Should().Be("hello world"); - // agent.ReceivedItems[1].Should().Be(42); - // } - - // [Fact] - // public async Task DelegateMessageToTestAgentAsync() - // { - // var runtime = new InMemoryAgentRuntimeFixture(); - // var client = runtime.AppHost.Services.GetRequiredService(); - // await client.PublishMessageAsync(new TextMessage() - // { - // Source = nameof(DelegateMessageToTestAgentAsync), - // TextMessage_ = "buffer" - // }, token: CancellationToken.None); - - // // wait for 10 seconds - // var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); - // while (!TestAgent.ReceivedMessages.ContainsKey(nameof(DelegateMessageToTestAgentAsync)) && !cts.Token.IsCancellationRequested) - // { - // await Task.Delay(100); - // } - - // TestAgent.ReceivedMessages[nameof(DelegateMessageToTestAgentAsync)].Should().NotBeNull(); - // } - - // [CollectionDefinition(Name)] - // public sealed class ClusterFixtureCollection : ICollectionFixture - // { - // public const string Name = nameof(ClusterFixtureCollection); - // } + [Fact] + public async Task AgentShouldSaveStateCorrectlyTest() + { + var runtime = new InProcessRuntime(); + await runtime.StartAsync(); + + Logger logger = new(new LoggerFactory()); + TestAgent agent = new TestAgent(new AgentId("TestType", "TestKey"), runtime, logger); + + var state = await agent.SaveStateAsync(); + + // Ensure state is a dictionary + state.Should().NotBeNull(); + state.Should().BeOfType>(); + state.Should().BeEmpty("Default SaveStateAsync should return an empty dictionary."); + + // Add a sample value and verify it updates correctly + state["testKey"] = "testValue"; + state.Should().ContainKey("testKey").WhoseValue.Should().Be("testValue"); + } } diff --git a/dotnet/test/Microsoft.AutoGen.Core.Tests/TestAgent.cs b/dotnet/test/Microsoft.AutoGen.Core.Tests/TestAgent.cs index bbd9506a5c1..af752ae0e61 100644 --- a/dotnet/test/Microsoft.AutoGen.Core.Tests/TestAgent.cs +++ b/dotnet/test/Microsoft.AutoGen.Core.Tests/TestAgent.cs @@ -59,7 +59,8 @@ public ValueTask HandleAsync(RpcTextMessage item, MessageContext message /// Key: source /// Value: message /// - public static Dictionary ReceivedMessages { get; private set; } = new(); + private readonly Dictionary _receivedMessages = new(); + public Dictionary ReceivedMessages => _receivedMessages; } [TypeSubscription("TestTopic")]