Files
agent-framework/dotnet/tests/Microsoft.Extensions.AI.Agents.UnitTests/MEAI/AssertExtensions.cs
T
westey a40eda48f1 .NET: Add Approval capabilities to FunctionInvokingChatClient (#457)
* Add Approval capabilities to FunctionInvokingChatClient

* Address PR comments.

* Address PR comments.

* Address PR comments.

* Address PR feedback, add sample, and fix bug plus unit test.

* Address PR comments
2025-08-25 10:41:10 +00:00

87 lines
3.4 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
// WARNING:
// This class has been temporarily copied here from MEAI, to allow prototyping
// functionality that will be moved to MEAI in the future.
// This file is not intended to be modified.
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using Xunit.Sdk;
namespace Microsoft.Extensions.AI;
internal static class AssertExtensions
{
/// <summary>
/// Asserts that the two function call parameters are equal, up to JSON equivalence.
/// </summary>
public static void EqualFunctionCallParameters(
IDictionary<string, object?>? expected,
IDictionary<string, object?>? actual,
JsonSerializerOptions? options = null)
{
if (expected is null || actual is null)
{
Assert.Equal(expected, actual);
return;
}
foreach (var expectedEntry in expected)
{
if (!actual.TryGetValue(expectedEntry.Key, out object? actualValue))
{
throw new XunitException($"Expected parameter '{expectedEntry.Key}' not found in actual value.");
}
AreJsonEquivalentValues(expectedEntry.Value, actualValue, options, propertyName: expectedEntry.Key);
}
if (expected.Count != actual.Count)
{
var extraParameters = actual
.Where(e => !expected.ContainsKey(e.Key))
.Select(e => $"'{e.Key}'")
.First();
throw new XunitException($"Actual value contains additional parameters {string.Join(", ", extraParameters)} not found in expected value.");
}
}
/// <summary>
/// Asserts that the two function call results are equal, up to JSON equivalence.
/// </summary>
public static void EqualFunctionCallResults(object? expected, object? actual, JsonSerializerOptions? options = null)
=> AreJsonEquivalentValues(expected, actual, options);
/// <summary>
/// Asserts that the two JSON values are equal.
/// </summary>
public static void EqualJsonValues(JsonElement expectedJson, JsonElement actualJson, string? propertyName = null)
{
if (!JsonNode.DeepEquals(
JsonSerializer.SerializeToNode(expectedJson, AIJsonUtilities.DefaultOptions),
JsonSerializer.SerializeToNode(actualJson, AIJsonUtilities.DefaultOptions)))
{
string message = propertyName is null
? $"JSON result does not match expected JSON.\r\nExpected: {expectedJson.GetRawText()}\r\nActual: {actualJson.GetRawText()}"
: $"Parameter '{propertyName}' does not match expected JSON.\r\nExpected: {expectedJson.GetRawText()}\r\nActual: {actualJson.GetRawText()}";
throw new XunitException(message);
}
}
private static void AreJsonEquivalentValues(object? expected, object? actual, JsonSerializerOptions? options, string? propertyName = null)
{
options ??= AIJsonUtilities.DefaultOptions;
JsonElement expectedElement = NormalizeToElement(expected, options);
JsonElement actualElement = NormalizeToElement(actual, options);
EqualJsonValues(expectedElement, actualElement, propertyName);
static JsonElement NormalizeToElement(object? value, JsonSerializerOptions options)
=> value is JsonElement e ? e : JsonSerializer.SerializeToElement(value, options);
}
}