From bbde248839b5ac5534a36792891170b4e5f060a0 Mon Sep 17 00:00:00 2001 From: Peter Ibekwe <109177538+peibekwe@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:40:10 -0800 Subject: [PATCH] .NET: Add unit tests for CreateConversation executor (#1915) * Add unit tests for create conversation executor * Update indentation and comment typo. --- .../MockAgentProvider.cs | 31 ++++++++ .../CreateConversationExecutorTest.cs | 75 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/MockAgentProvider.cs create mode 100644 dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/ObjectModel/CreateConversationExecutorTest.cs diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/MockAgentProvider.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/MockAgentProvider.cs new file mode 100644 index 0000000000..67e4c68c5e --- /dev/null +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/MockAgentProvider.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Moq; + +namespace Microsoft.Agents.AI.Workflows.Declarative.UnitTests; + +/// +/// Mock implementation of for unit testing purposes. +/// +internal sealed class MockAgentProvider : Mock +{ + public IList ExistingConversationIds { get; } = []; + + public MockAgentProvider() + { + this.Setup(provider => provider.CreateConversationAsync(It.IsAny())) + .Returns(() => Task.FromResult(this.CreateConversationId())); + } + + private string CreateConversationId() + { + string newConversationId = Guid.NewGuid().ToString("N"); + this.ExistingConversationIds.Add(newConversationId); + + return newConversationId; + } +} diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/ObjectModel/CreateConversationExecutorTest.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/ObjectModel/CreateConversationExecutorTest.cs new file mode 100644 index 0000000000..5636b3e65f --- /dev/null +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/ObjectModel/CreateConversationExecutorTest.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Agents.AI.Workflows.Declarative.ObjectModel; +using Microsoft.Agents.AI.Workflows.Declarative.PowerFx; +using Microsoft.Bot.ObjectModel; +using Microsoft.PowerFx.Types; +using Xunit.Abstractions; + +namespace Microsoft.Agents.AI.Workflows.Declarative.UnitTests.ObjectModel; + +/// +/// Tests for . +/// +public sealed class CreateConversationExecutorTest(ITestOutputHelper output) : WorkflowActionExecutorTest(output) +{ + [Fact] + public async Task CreateNewConversationAsync() + { + // Arrange, Act, Assert + await this.ExecuteTestAsync(nameof(CreateNewConversationAsync), + "TestConversationId", + executionIteration: 1); + } + + [Fact] + public async Task CreateMultipleConversationsAsync() + { + // Arrange, Act, Assert + await this.ExecuteTestAsync(nameof(CreateMultipleConversationsAsync), + "TestConversationId", + executionIteration: 4); + } + + private async Task ExecuteTestAsync( + string displayName, + string variableName, + int executionIteration) + { + // Arrange + // Initialize state to simulate workflow environment. + this.State.InitializeSystem(); + CreateConversation model = this.CreateModel( + this.FormatDisplayName(displayName), + FormatVariablePath(variableName)); + MockAgentProvider mockAgentProvider = new(); + CreateConversationExecutor action = new(model, mockAgentProvider.Object, this.State); + + // Act + int expectedIterationCount = executionIteration; + while (executionIteration-- > 0) + { + await this.ExecuteAsync(action); + } + + // Assert + VerifyModel(model, action); + Assert.Equal(expected: expectedIterationCount, actual: mockAgentProvider.ExistingConversationIds.Count); + this.VerifyState("TestConversationId", FormulaValue.New(mockAgentProvider.ExistingConversationIds.Last())); + } + + private CreateConversation CreateModel(string displayName, string conversationIdVariable) + { + CreateConversation.Builder actionBuilder = + new() + { + Id = this.CreateActionId(), + DisplayName = this.FormatDisplayName(displayName), + ConversationId = PropertyPath.Create(conversationIdVariable) + }; + + return AssignParent(actionBuilder); + } +}