add tests
This commit is contained in:
321
ChatBot.Tests/Services/ChatServiceTests.cs
Normal file
321
ChatBot.Tests/Services/ChatServiceTests.cs
Normal file
@@ -0,0 +1,321 @@
|
||||
using ChatBot.Models;
|
||||
using ChatBot.Models.Configuration;
|
||||
using ChatBot.Models.Dto;
|
||||
using ChatBot.Services;
|
||||
using ChatBot.Services.Interfaces;
|
||||
using ChatBot.Tests.TestUtilities;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
|
||||
namespace ChatBot.Tests.Services;
|
||||
|
||||
public class ChatServiceTests : UnitTestBase
|
||||
{
|
||||
private readonly Mock<ILogger<ChatService>> _loggerMock;
|
||||
private readonly Mock<IAIService> _aiServiceMock;
|
||||
private readonly Mock<ISessionStorage> _sessionStorageMock;
|
||||
private readonly Mock<IHistoryCompressionService> _compressionServiceMock;
|
||||
private readonly AISettings _aiSettings;
|
||||
private readonly ChatService _chatService;
|
||||
|
||||
public ChatServiceTests()
|
||||
{
|
||||
_loggerMock = TestDataBuilder.Mocks.CreateLoggerMock<ChatService>();
|
||||
_aiServiceMock = TestDataBuilder.Mocks.CreateAIServiceMock();
|
||||
_sessionStorageMock = TestDataBuilder.Mocks.CreateSessionStorageMock();
|
||||
_compressionServiceMock = TestDataBuilder.Mocks.CreateCompressionServiceMock();
|
||||
_aiSettings = TestDataBuilder.Configurations.CreateAISettings();
|
||||
|
||||
var optionsMock = TestDataBuilder.Mocks.CreateOptionsMock(_aiSettings);
|
||||
|
||||
_chatService = new ChatService(
|
||||
_loggerMock.Object,
|
||||
_aiServiceMock.Object,
|
||||
_sessionStorageMock.Object,
|
||||
optionsMock.Object,
|
||||
_compressionServiceMock.Object
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrCreateSession_ShouldCreateNewSession_WhenSessionDoesNotExist()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var chatType = "private";
|
||||
var chatTitle = "Test Chat";
|
||||
|
||||
// Act
|
||||
var session = _chatService.GetOrCreateSession(chatId, chatType, chatTitle);
|
||||
|
||||
// Assert
|
||||
session.Should().NotBeNull();
|
||||
session.ChatId.Should().Be(chatId);
|
||||
session.ChatType.Should().Be(chatType);
|
||||
session.ChatTitle.Should().Be(chatTitle);
|
||||
|
||||
_sessionStorageMock.Verify(x => x.GetOrCreate(chatId, chatType, chatTitle), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrCreateSession_ShouldSetCompressionService_WhenCompressionIsEnabled()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
_aiSettings.EnableHistoryCompression = true;
|
||||
|
||||
// Act
|
||||
var session = _chatService.GetOrCreateSession(chatId);
|
||||
|
||||
// Assert
|
||||
session.Should().NotBeNull();
|
||||
_sessionStorageMock.Verify(x => x.GetOrCreate(chatId, "private", ""), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessMessageAsync_ShouldProcessMessageSuccessfully_WhenValidInput()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var username = "testuser";
|
||||
var message = "Hello, bot!";
|
||||
var expectedResponse = "Hello! How can I help you?";
|
||||
|
||||
_aiServiceMock
|
||||
.Setup(x =>
|
||||
x.GenerateChatCompletionWithCompressionAsync(
|
||||
It.IsAny<List<ChatBot.Models.Dto.ChatMessage>>(),
|
||||
It.IsAny<CancellationToken>()
|
||||
)
|
||||
)
|
||||
.ReturnsAsync(expectedResponse);
|
||||
|
||||
// Act
|
||||
var result = await _chatService.ProcessMessageAsync(chatId, username, message);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(expectedResponse);
|
||||
_sessionStorageMock.Verify(
|
||||
x => x.SaveSessionAsync(It.IsAny<ChatBot.Models.ChatSession>()),
|
||||
Times.AtLeastOnce
|
||||
);
|
||||
_aiServiceMock.Verify(
|
||||
x =>
|
||||
x.GenerateChatCompletionWithCompressionAsync(
|
||||
It.IsAny<List<ChatBot.Models.Dto.ChatMessage>>(),
|
||||
It.IsAny<CancellationToken>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessMessageAsync_ShouldReturnEmptyString_WhenAIResponseIsEmptyMarker()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var username = "testuser";
|
||||
var message = "Hello, bot!";
|
||||
var emptyResponse = "{empty}";
|
||||
|
||||
_aiServiceMock
|
||||
.Setup(x =>
|
||||
x.GenerateChatCompletionWithCompressionAsync(
|
||||
It.IsAny<List<ChatBot.Models.Dto.ChatMessage>>(),
|
||||
It.IsAny<CancellationToken>()
|
||||
)
|
||||
)
|
||||
.ReturnsAsync(emptyResponse);
|
||||
|
||||
// Act
|
||||
var result = await _chatService.ProcessMessageAsync(chatId, username, message);
|
||||
|
||||
// Assert
|
||||
result.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessMessageAsync_ShouldReturnErrorMessage_WhenAIResponseIsNull()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var username = "testuser";
|
||||
var message = "Hello, bot!";
|
||||
|
||||
_aiServiceMock
|
||||
.Setup(x =>
|
||||
x.GenerateChatCompletionWithCompressionAsync(
|
||||
It.IsAny<List<ChatBot.Models.Dto.ChatMessage>>(),
|
||||
It.IsAny<CancellationToken>()
|
||||
)
|
||||
)
|
||||
.ReturnsAsync((string)null!);
|
||||
|
||||
// Act
|
||||
var result = await _chatService.ProcessMessageAsync(chatId, username, message);
|
||||
|
||||
// Assert
|
||||
result.Should().Be("Извините, произошла ошибка при генерации ответа.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessMessageAsync_ShouldHandleException_WhenErrorOccurs()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var username = "testuser";
|
||||
var message = "Hello, bot!";
|
||||
|
||||
_aiServiceMock
|
||||
.Setup(x =>
|
||||
x.GenerateChatCompletionWithCompressionAsync(
|
||||
It.IsAny<List<ChatBot.Models.Dto.ChatMessage>>(),
|
||||
It.IsAny<CancellationToken>()
|
||||
)
|
||||
)
|
||||
.ThrowsAsync(new Exception("Test exception"));
|
||||
|
||||
// Act
|
||||
var result = await _chatService.ProcessMessageAsync(chatId, username, message);
|
||||
|
||||
// Assert
|
||||
result.Should().Be("Извините, произошла ошибка при обработке вашего сообщения.");
|
||||
// Verify that error was logged
|
||||
// In a real test, we would verify the logger calls
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateSessionParametersAsync_ShouldUpdateSession_WhenSessionExists()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var newModel = "llama3.2";
|
||||
var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId);
|
||||
|
||||
_sessionStorageMock.Setup(x => x.Get(chatId)).Returns(session);
|
||||
|
||||
// Act
|
||||
await _chatService.UpdateSessionParametersAsync(chatId, newModel);
|
||||
|
||||
// Assert
|
||||
session.Model.Should().Be(newModel);
|
||||
_sessionStorageMock.Verify(x => x.SaveSessionAsync(session), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateSessionParametersAsync_ShouldNotUpdate_WhenSessionDoesNotExist()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var newModel = "llama3.2";
|
||||
|
||||
_sessionStorageMock.Setup(x => x.Get(chatId)).Returns((ChatBot.Models.ChatSession?)null);
|
||||
|
||||
// Act
|
||||
await _chatService.UpdateSessionParametersAsync(chatId, newModel);
|
||||
|
||||
// Assert
|
||||
_sessionStorageMock.Verify(
|
||||
x => x.SaveSessionAsync(It.IsAny<ChatBot.Models.ChatSession>()),
|
||||
Times.Never
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClearHistoryAsync_ShouldClearHistory_WhenSessionExists()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var session = TestDataBuilder.ChatSessions.CreateSessionWithMessages(chatId, 5);
|
||||
|
||||
_sessionStorageMock.Setup(x => x.Get(chatId)).Returns(session);
|
||||
|
||||
// Act
|
||||
await _chatService.ClearHistoryAsync(chatId);
|
||||
|
||||
// Assert
|
||||
session.GetMessageCount().Should().Be(0);
|
||||
_sessionStorageMock.Verify(x => x.SaveSessionAsync(session), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetSession_ShouldReturnSession_WhenSessionExists()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
var session = TestDataBuilder.ChatSessions.CreateBasicSession(chatId);
|
||||
|
||||
_sessionStorageMock.Setup(x => x.Get(chatId)).Returns(session);
|
||||
|
||||
// Act
|
||||
var result = _chatService.GetSession(chatId);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(session);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetSession_ShouldReturnNull_WhenSessionDoesNotExist()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
|
||||
_sessionStorageMock.Setup(x => x.Get(chatId)).Returns((ChatBot.Models.ChatSession?)null);
|
||||
|
||||
// Act
|
||||
var result = _chatService.GetSession(chatId);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoveSession_ShouldReturnTrue_WhenSessionExists()
|
||||
{
|
||||
// Arrange
|
||||
var chatId = 12345L;
|
||||
|
||||
_sessionStorageMock.Setup(x => x.Remove(chatId)).Returns(true);
|
||||
|
||||
// Act
|
||||
var result = _chatService.RemoveSession(chatId);
|
||||
|
||||
// Assert
|
||||
result.Should().BeTrue();
|
||||
_sessionStorageMock.Verify(x => x.Remove(chatId), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActiveSessionsCount_ShouldReturnCorrectCount()
|
||||
{
|
||||
// Arrange
|
||||
var expectedCount = 5;
|
||||
|
||||
_sessionStorageMock.Setup(x => x.GetActiveSessionsCount()).Returns(expectedCount);
|
||||
|
||||
// Act
|
||||
var result = _chatService.GetActiveSessionsCount();
|
||||
|
||||
// Assert
|
||||
result.Should().Be(expectedCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CleanupOldSessions_ShouldReturnCleanedCount()
|
||||
{
|
||||
// Arrange
|
||||
var hoursOld = 24;
|
||||
var expectedCleaned = 3;
|
||||
|
||||
_sessionStorageMock.Setup(x => x.CleanupOldSessions(hoursOld)).Returns(expectedCleaned);
|
||||
|
||||
// Act
|
||||
var result = _chatService.CleanupOldSessions(hoursOld);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(expectedCleaned);
|
||||
_sessionStorageMock.Verify(x => x.CleanupOldSessions(hoursOld), Times.Once);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user