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);
+ }
+}