应文浩wenhao.ying@xiaobao100.com bce2612b64 feat: 完善具体实现
2026-04-06 15:25:34 +08:00

208 lines
5.5 KiB
C#

using Xunit;
using FluentAssertions;
using NSubstitute;
using System;
using System.Text.Json;
using FreeCode.Core.Models;
using FreeCode.Core.Enums;
namespace FreeCode.Tests.Unit.Models;
public sealed class MessageTests
{
[Fact]
public void Message_HoldsRequiredFields()
{
var timestamp = new DateTime(2026, 4, 6, 10, 0, 0, DateTimeKind.Utc);
var message = new Message
{
MessageId = "msg-1",
Role = MessageRole.User,
Content = "hello",
Timestamp = timestamp,
ToolUseId = "tool-1",
ToolName = "bash"
};
message.MessageId.Should().Be("msg-1");
message.Role.Should().Be(MessageRole.User);
message.Content.Should().Be("hello");
message.Timestamp.Should().Be(timestamp);
message.ToolUseId.Should().Be("tool-1");
message.ToolName.Should().Be("bash");
}
[Fact]
public void Message_DefaultTimestampIsUtcNowBased()
{
var before = DateTime.UtcNow.AddSeconds(-1);
var message = new Message
{
MessageId = "msg-1",
Role = MessageRole.Assistant,
Content = "reply"
};
var after = DateTime.UtcNow.AddSeconds(1);
message.Timestamp.Should().BeOnOrAfter(before);
message.Timestamp.Should().BeOnOrBefore(after);
}
[Fact]
public void Message_AllowsNullContent()
{
var message = new Message
{
MessageId = "msg-1",
Role = MessageRole.User,
Content = null,
Timestamp = new DateTime(2026, 4, 6, 10, 0, 0, DateTimeKind.Utc)
};
message.Content.Should().BeNull();
}
[Fact]
public void Message_CanStoreStringContent()
{
var message = CreateMessage(content: "plain text");
message.Content.Should().Be("plain text");
}
[Fact]
public void Message_CanStoreJsonContent()
{
var payload = ParseJson("{\"type\":\"text\",\"value\":\"hi\"}");
var message = CreateMessage(content: payload);
message.Content.Should().BeOfType<JsonElement>();
((JsonElement)message.Content!).GetProperty("type").GetString().Should().Be("text");
}
[Fact]
public void Message_CanStoreSubstitutedContentObject()
{
var disposable = new object();
var message = CreateMessage(content: disposable);
message.Content.Should().BeSameAs(disposable);
}
[Fact]
public void Message_ToolFieldsDefaultToNull()
{
var message = CreateMessage();
message.ToolUseId.Should().BeNull();
message.ToolName.Should().BeNull();
}
[Fact]
public void Message_CanStoreToolMetadata()
{
var message = CreateMessage(toolUseId: "tool-1", toolName: "read");
message.ToolUseId.Should().Be("tool-1");
message.ToolName.Should().Be("read");
}
[Fact]
public void Message_UsesValueEqualityForEquivalentValues()
{
var timestamp = new DateTime(2026, 4, 6, 10, 0, 0, DateTimeKind.Utc);
var left = CreateMessage(timestamp: timestamp);
var right = CreateMessage(timestamp: timestamp);
left.Should().Be(right);
}
[Fact]
public void Message_IsNotEqualWhenRoleDiffers()
{
var timestamp = new DateTime(2026, 4, 6, 10, 0, 0, DateTimeKind.Utc);
var left = CreateMessage(role: MessageRole.User, timestamp: timestamp);
var right = CreateMessage(role: MessageRole.Assistant, timestamp: timestamp);
left.Should().NotBe(right);
}
[Fact]
public void Message_WithExpressionClonesRecordWithChange()
{
var original = CreateMessage(content: "before");
var clone = original with { Content = "after" };
clone.MessageId.Should().Be(original.MessageId);
clone.Role.Should().Be(original.Role);
clone.Content.Should().Be("after");
original.Content.Should().Be("before");
}
[Fact]
public void Message_AllowsEmptyMessageId()
{
var message = CreateMessage(messageId: string.Empty);
message.MessageId.Should().BeEmpty();
}
[Fact]
public void Message_AllowsEmptyToolUseId()
{
var message = CreateMessage(toolUseId: string.Empty);
message.ToolUseId.Should().BeEmpty();
}
[Fact]
public void Message_AllowsEmptyToolName()
{
var message = CreateMessage(toolName: string.Empty);
message.ToolName.Should().BeEmpty();
}
[Theory]
[InlineData(MessageRole.User)]
[InlineData(MessageRole.Assistant)]
[InlineData(MessageRole.System)]
[InlineData(MessageRole.Tool)]
public void Message_HoldsEachRole(MessageRole role)
{
var message = CreateMessage(role: role);
message.Role.Should().Be(role);
}
private static Message CreateMessage(
string messageId = "msg-1",
MessageRole role = MessageRole.User,
object? content = null,
DateTime? timestamp = null,
string? toolUseId = null,
string? toolName = null)
{
return new Message
{
MessageId = messageId,
Role = role,
Content = content ?? "hello",
Timestamp = timestamp ?? new DateTime(2026, 4, 6, 10, 0, 0, DateTimeKind.Utc),
ToolUseId = toolUseId,
ToolName = toolName
};
}
private static JsonElement ParseJson(string json)
{
using var document = JsonDocument.Parse(json);
return document.RootElement.Clone();
}
}