Files
agent-framework/dotnet/tests/Microsoft.Agents.Orchestration.UnitTests/HandoffsTests.cs
T
7c8ec5ec19 .NET Port Agent Orchestration (#107)
* Checkpoint

* Checkpoint

* Namespaces

* Namespace

* Cleanup

* Namespace order

* Fix sync

* Formatting

* Formatting

* Namespace

* Namespace order

* Code convention

* Naming

* Naming

* Text handling

* Text handling

* Namespace

* Namespace order

* Namespace ordering

* Test

* ValueTask

* net472

* Test fix

* Fix namespace (net472)

* Namespace

* Fix conditional namespace

* Fix type expression

* Compatibility and cleanup

* Sample compatibility

* Sample compat

* Test compat

* modifier order

* Simply http-stub

* Formating fix for unit-test

* Fix test

* Real fix

* Test clean-up

* Update dotnet/src/Microsoft.Agents.Orchestration/Handoff/HandoffOrchestration.cs

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

* Fix build errors after merging

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
2025-07-08 13:04:34 -04:00

237 lines
7.9 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System;
using Microsoft.Agents.Orchestration.Handoff;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.AI.Agents;
using Moq;
namespace Microsoft.Agents.Orchestration.UnitTest;
public class HandoffsTests
{
[Fact]
public void EmptyConstructorsCreateEmptyCollections()
{
AgentHandoffs agentHandoffs = [];
Assert.Empty(agentHandoffs);
OrchestrationHandoffs orchestrationHandoffs = new("first");
Assert.Empty(orchestrationHandoffs);
Assert.Equal("first", orchestrationHandoffs.FirstAgentName);
}
[Fact]
public void DictionaryConstructorsInvalidFirstAgent()
{
Assert.Throws<ArgumentNullException>(() => new OrchestrationHandoffs((string)null!));
Assert.Throws<ArgumentException>(() => new OrchestrationHandoffs(string.Empty));
Assert.Throws<ArgumentException>(() => new OrchestrationHandoffs(" "));
}
[Fact]
public void AddWithAgentObjectsCreatesHandoffRelationships()
{
// Arrange
OrchestrationHandoffs handoffs = new("source");
Agent sourceAgent = CreateAgent("source", "Source Agent");
Agent targetAgent1 = CreateAgent("target1", "Target Agent 1");
Agent targetAgent2 = CreateAgent("target2", "Target Agent 2");
// Act
handoffs.Add(sourceAgent, targetAgent1, targetAgent2);
// Assert
Assert.Single(handoffs);
Assert.Equal("source", handoffs.FirstAgentName);
Assert.True(handoffs.ContainsKey("source"));
AgentHandoffs sourceHandoffs = handoffs["source"];
Assert.Equal(2, sourceHandoffs.Count);
Assert.Equal("Target Agent 1", sourceHandoffs["target1"]);
Assert.Equal("Target Agent 2", sourceHandoffs["target2"]);
}
[Fact]
public void AddWithAgentAndCustomDescriptionUsesCustomDescription()
{
// Arrange
OrchestrationHandoffs handoffs = new("source");
Agent sourceAgent = CreateAgent("source", "Source Agent");
Agent targetAgent = CreateAgent("target", "Target Agent");
string customDescription = "Custom handoff description";
// Act
handoffs.Add(sourceAgent, targetAgent, customDescription);
// Assert
Assert.Single(handoffs);
Assert.Equal("source", handoffs.FirstAgentName);
AgentHandoffs sourceHandoffs = handoffs["source"];
Assert.Single(sourceHandoffs);
Assert.Equal(customDescription, sourceHandoffs["target"]);
}
[Fact]
public void AddWithAgentAndTargetNameAddsHandoffWithDescription()
{
// Arrange
OrchestrationHandoffs handoffs = new("source");
Agent sourceAgent = CreateAgent("source", "Source Agent");
string targetName = "targetName";
string description = "Target description";
// Act
handoffs.Add(sourceAgent, targetName, description);
// Assert
Assert.Single(handoffs);
Assert.Equal("source", handoffs.FirstAgentName);
AgentHandoffs sourceHandoffs = handoffs["source"];
Assert.Single(sourceHandoffs);
Assert.Equal(description, sourceHandoffs[targetName]);
}
[Fact]
public void AddWithSourceNameAndTargetNameAddsHandoffWithDescription()
{
// Arrange
OrchestrationHandoffs handoffs = new("sourceName");
string sourceName = "sourceName";
string targetName = "targetName";
string description = "Target description";
// Act
handoffs.Add(sourceName, targetName, description);
// Assert
Assert.Single(handoffs);
Assert.Equal("sourceName", handoffs.FirstAgentName);
AgentHandoffs sourceHandoffs = handoffs[sourceName];
Assert.Single(sourceHandoffs);
Assert.Equal(description, sourceHandoffs[targetName]);
}
[Fact]
public void AddWithMultipleSourcesAndTargetsCreatesCorrectStructure()
{
// Arrange
OrchestrationHandoffs handoffs = new("source1");
Agent source1 = CreateAgent("source1", "Source Agent 1");
Agent source2 = CreateAgent("source2", "Source Agent 2");
Agent target1 = CreateAgent("target1", "Target Agent 1");
Agent target2 = CreateAgent("target2", "Target Agent 2");
Agent target3 = CreateAgent("target3", "Target Agent 3");
// Act
handoffs.Add(source1, target1, target2);
handoffs.Add(source2, target2, target3);
handoffs.Add(source1, target3, "Custom description");
// Assert
Assert.Equal(2, handoffs.Count);
Assert.Equal("source1", handoffs.FirstAgentName);
// Check source1's targets
AgentHandoffs source1Handoffs = handoffs["source1"];
Assert.Equal(3, source1Handoffs.Count);
Assert.Equal("Target Agent 1", source1Handoffs["target1"]);
Assert.Equal("Target Agent 2", source1Handoffs["target2"]);
Assert.Equal("Custom description", source1Handoffs["target3"]);
// Check source2's targets
AgentHandoffs source2Handoffs = handoffs["source2"];
Assert.Equal(2, source2Handoffs.Count);
Assert.Equal("Target Agent 2", source2Handoffs["target2"]);
Assert.Equal("Target Agent 3", source2Handoffs["target3"]);
}
[Fact]
public void StaticAddCreatesNewOrchestrationHandoffs()
{
// Arrange
Agent source = CreateAgent("source", "Source Agent");
Agent target1 = CreateAgent("target1", "Target Agent 1");
Agent target2 = CreateAgent("target2", "Target Agent 2");
// Act
OrchestrationHandoffs handoffs =
OrchestrationHandoffs
.StartWith(source)
.Add(source, target1, target2);
// Assert
Assert.NotNull(handoffs);
Assert.Equal(source.Id, handoffs.FirstAgentName);
Assert.Single(handoffs);
Assert.True(handoffs.ContainsKey("source"));
AgentHandoffs sourceHandoffs = handoffs["source"];
Assert.Equal(2, sourceHandoffs.Count);
Assert.Equal("Target Agent 1", sourceHandoffs["target1"]);
Assert.Equal("Target Agent 2", sourceHandoffs["target2"]);
}
[Fact]
public void AddWithAgentsWithNoNameUsesId()
{
// Arrange
OrchestrationHandoffs handoffs = new("source-id");
Agent sourceAgent = CreateAgent(id: "source-id", name: null);
Agent targetAgent = CreateAgent(id: "target-id", name: null, description: "Target Description");
// Act
handoffs.Add(sourceAgent, targetAgent);
// Assert
Assert.Single(handoffs);
Assert.Equal("source-id", handoffs.FirstAgentName);
Assert.True(handoffs.ContainsKey("source-id"));
AgentHandoffs sourceHandoffs = handoffs["source-id"];
Assert.Single(sourceHandoffs);
Assert.Equal("Target Description", sourceHandoffs["target-id"]);
}
[Fact]
public void AddWithTargetWithNoDescriptionUsesEmptyString()
{
// Arrange
OrchestrationHandoffs handoffs = new("source");
Agent sourceAgent = CreateAgent("source", "Source Agent");
Agent targetAgent = CreateAgent("target", null);
// Act
handoffs.Add(sourceAgent, targetAgent);
// Assert
Assert.Single(handoffs);
Assert.Equal("source", handoffs.FirstAgentName);
AgentHandoffs sourceHandoffs = handoffs["source"];
Assert.Single(sourceHandoffs);
Assert.Equal(string.Empty, sourceHandoffs["target"]);
}
private static ChatClientAgent CreateAgent(string id, string? description = null, string? name = null)
{
Mock<IChatClient> mockClient = new(MockBehavior.Loose);
ChatClientAgentOptions options =
new()
{
Id = id,
Name = name,
Description = description,
};
ChatClientAgent mockAgent = new(mockClient.Object, options);
return mockAgent;
}
}