using ChatBot.Models.Dto; using ChatBot.Services; using ChatBot.Services.Interfaces; using ChatBot.Tests.TestUtilities; using FluentAssertions; using Moq; namespace ChatBot.Tests.Services.Interfaces; public class IHistoryCompressionServiceTests : UnitTestBase { [Fact] public void IHistoryCompressionService_ShouldHaveCorrectMethodSignatures() { // Arrange & Act var interfaceType = typeof(IHistoryCompressionService); var methods = interfaceType.GetMethods(); // Assert methods.Should().HaveCount(2); // CompressHistoryAsync method var compressHistoryAsyncMethod = methods.FirstOrDefault(m => m.Name == "CompressHistoryAsync" ); compressHistoryAsyncMethod.Should().NotBeNull(); compressHistoryAsyncMethod!.ReturnType.Should().Be>>(); compressHistoryAsyncMethod.GetParameters().Should().HaveCount(3); compressHistoryAsyncMethod .GetParameters()[0] .ParameterType.Should() .Be>(); compressHistoryAsyncMethod.GetParameters()[1].ParameterType.Should().Be(); compressHistoryAsyncMethod .GetParameters()[2] .ParameterType.Should() .Be(); // ShouldCompress method var shouldCompressMethod = methods.FirstOrDefault(m => m.Name == "ShouldCompress"); shouldCompressMethod.Should().NotBeNull(); shouldCompressMethod!.ReturnType.Should().Be(); shouldCompressMethod.GetParameters().Should().HaveCount(2); shouldCompressMethod.GetParameters()[0].ParameterType.Should().Be(); shouldCompressMethod.GetParameters()[1].ParameterType.Should().Be(); } [Fact] public void IHistoryCompressionService_ShouldBeImplementedByHistoryCompressionService() { // Arrange & Act var historyCompressionServiceType = typeof(HistoryCompressionService); var interfaceType = typeof(IHistoryCompressionService); // Assert interfaceType.IsAssignableFrom(historyCompressionServiceType).Should().BeTrue(); } [Fact] public async Task IHistoryCompressionService_CompressHistoryAsync_ShouldReturnCompressedMessages() { // Arrange var mock = new Mock(); var messages = new List { new() { Role = "user", Content = "Message 1" }, new() { Role = "assistant", Content = "Response 1" }, new() { Role = "user", Content = "Message 2" }, new() { Role = "assistant", Content = "Response 2" }, }; var targetCount = 2; var cancellationToken = CancellationToken.None; var expectedCompressedMessages = new List { new() { Role = "user", Content = "Compressed message" }, new() { Role = "assistant", Content = "Compressed response" }, }; mock.Setup(x => x.CompressHistoryAsync( It.IsAny>(), It.IsAny(), It.IsAny() ) ) .ReturnsAsync(expectedCompressedMessages); // Act var result = await mock.Object.CompressHistoryAsync( messages, targetCount, cancellationToken ); // Assert result.Should().BeEquivalentTo(expectedCompressedMessages); mock.Verify( x => x.CompressHistoryAsync(messages, targetCount, cancellationToken), Times.Once ); } [Fact] public async Task IHistoryCompressionService_CompressHistoryAsync_ShouldHandleEmptyMessages() { // Arrange var mock = new Mock(); var messages = new List(); var targetCount = 5; var cancellationToken = CancellationToken.None; var expectedCompressedMessages = new List(); mock.Setup(x => x.CompressHistoryAsync( It.IsAny>(), It.IsAny(), It.IsAny() ) ) .ReturnsAsync(expectedCompressedMessages); // Act var result = await mock.Object.CompressHistoryAsync( messages, targetCount, cancellationToken ); // Assert result.Should().BeEquivalentTo(expectedCompressedMessages); mock.Verify( x => x.CompressHistoryAsync(messages, targetCount, cancellationToken), Times.Once ); } [Fact] public async Task IHistoryCompressionService_CompressHistoryAsync_ShouldHandleLargeMessageList() { // Arrange var mock = new Mock(); var messages = new List(); for (int i = 0; i < 100; i++) { messages.Add(new() { Role = "user", Content = $"Message {i}" }); } var targetCount = 10; var cancellationToken = CancellationToken.None; var expectedCompressedMessages = new List { new() { Role = "user", Content = "Compressed summary" }, }; mock.Setup(x => x.CompressHistoryAsync( It.IsAny>(), It.IsAny(), It.IsAny() ) ) .ReturnsAsync(expectedCompressedMessages); // Act var result = await mock.Object.CompressHistoryAsync( messages, targetCount, cancellationToken ); // Assert result.Should().BeEquivalentTo(expectedCompressedMessages); mock.Verify( x => x.CompressHistoryAsync(messages, targetCount, cancellationToken), Times.Once ); } [Fact] public async Task IHistoryCompressionService_CompressHistoryAsync_ShouldHandleCancellationToken() { // Arrange var mock = new Mock(); var messages = new List { new() { Role = "user", Content = "Test message" }, }; var targetCount = 1; var cancellationToken = new CancellationToken(true); // Cancelled token var expectedCompressedMessages = new List(); mock.Setup(x => x.CompressHistoryAsync( It.IsAny>(), It.IsAny(), It.IsAny() ) ) .ReturnsAsync(expectedCompressedMessages); // Act var result = await mock.Object.CompressHistoryAsync( messages, targetCount, cancellationToken ); // Assert result.Should().BeEquivalentTo(expectedCompressedMessages); mock.Verify( x => x.CompressHistoryAsync(messages, targetCount, cancellationToken), Times.Once ); } [Fact] public void IHistoryCompressionService_ShouldCompress_ShouldReturnTrue_WhenMessageCountExceedsThreshold() { // Arrange var mock = new Mock(); var messageCount = 15; var threshold = 10; var expectedResult = true; mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.ShouldCompress(messageCount, threshold); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.ShouldCompress(messageCount, threshold), Times.Once); } [Fact] public void IHistoryCompressionService_ShouldCompress_ShouldReturnFalse_WhenMessageCountIsBelowThreshold() { // Arrange var mock = new Mock(); var messageCount = 5; var threshold = 10; var expectedResult = false; mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.ShouldCompress(messageCount, threshold); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.ShouldCompress(messageCount, threshold), Times.Once); } [Fact] public void IHistoryCompressionService_ShouldCompress_ShouldReturnFalse_WhenMessageCountEqualsThreshold() { // Arrange var mock = new Mock(); var messageCount = 10; var threshold = 10; var expectedResult = false; mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.ShouldCompress(messageCount, threshold); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.ShouldCompress(messageCount, threshold), Times.Once); } [Fact] public void IHistoryCompressionService_ShouldCompress_ShouldHandleZeroValues() { // Arrange var mock = new Mock(); var messageCount = 0; var threshold = 0; var expectedResult = false; mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.ShouldCompress(messageCount, threshold); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.ShouldCompress(messageCount, threshold), Times.Once); } [Fact] public void IHistoryCompressionService_ShouldCompress_ShouldHandleNegativeValues() { // Arrange var mock = new Mock(); var messageCount = -5; var threshold = -10; var expectedResult = false; mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.ShouldCompress(messageCount, threshold); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.ShouldCompress(messageCount, threshold), Times.Once); } [Fact] public void IHistoryCompressionService_ShouldCompress_ShouldHandleLargeValues() { // Arrange var mock = new Mock(); var messageCount = int.MaxValue; var threshold = int.MaxValue - 1; var expectedResult = true; mock.Setup(x => x.ShouldCompress(It.IsAny(), It.IsAny())).Returns(expectedResult); // Act var result = mock.Object.ShouldCompress(messageCount, threshold); // Assert result.Should().Be(expectedResult); mock.Verify(x => x.ShouldCompress(messageCount, threshold), Times.Once); } [Fact] public void IHistoryCompressionService_ShouldBePublicInterface() { // Arrange & Act var interfaceType = typeof(IHistoryCompressionService); // Assert interfaceType.IsPublic.Should().BeTrue(); interfaceType.IsInterface.Should().BeTrue(); } [Fact] public void IHistoryCompressionService_ShouldHaveCorrectNamespace() { // Arrange & Act var interfaceType = typeof(IHistoryCompressionService); // Assert interfaceType.Namespace.Should().Be("ChatBot.Services.Interfaces"); } [Fact] public void IHistoryCompressionService_ShouldHaveCorrectGenericConstraints() { // Arrange & Act var interfaceType = typeof(IHistoryCompressionService); var methods = interfaceType.GetMethods(); // Assert // All methods should be public methods.All(m => m.IsPublic).Should().BeTrue(); // CompressHistoryAsync should have default parameter for CancellationToken var compressMethod = methods.First(m => m.Name == "CompressHistoryAsync"); compressMethod.GetParameters()[2].HasDefaultValue.Should().BeTrue(); // Note: Default value for CancellationToken in interface might be null compressMethod.GetParameters()[2].DefaultValue.Should().BeNull(); } }