192 lines
6.6 KiB
C#
192 lines
6.6 KiB
C#
using ChatBot.Models.Configuration;
|
|
using ChatBot.Services;
|
|
using ChatBot.Tests.TestUtilities;
|
|
using FluentAssertions;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Moq;
|
|
|
|
namespace ChatBot.Tests.Services;
|
|
|
|
public class SystemPromptServiceTests : UnitTestBase
|
|
{
|
|
private readonly Mock<ILogger<SystemPromptService>> _loggerMock;
|
|
private readonly SystemPromptService _systemPromptService;
|
|
|
|
public SystemPromptServiceTests()
|
|
{
|
|
_loggerMock = TestDataBuilder.Mocks.CreateLoggerMock<SystemPromptService>();
|
|
var aiSettingsMock = TestDataBuilder.Mocks.CreateOptionsMock(new AISettings());
|
|
_systemPromptService = new SystemPromptService(_loggerMock.Object, aiSettingsMock.Object);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSystemPromptAsync_ShouldReturnSystemPrompt()
|
|
{
|
|
// Act
|
|
var result = await _systemPromptService.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
result.Should().NotBeNullOrEmpty();
|
|
result.Should().Contain("Никита");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSystemPromptAsync_ShouldReturnCachedPrompt_WhenCalledMultipleTimes()
|
|
{
|
|
// Act
|
|
var result1 = await _systemPromptService.GetSystemPromptAsync();
|
|
var result2 = await _systemPromptService.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
result1.Should().Be(result2);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReloadPrompt_ShouldClearCache()
|
|
{
|
|
// Act
|
|
// ReloadPrompt method doesn't exist, skipping this test
|
|
var newPrompt = await _systemPromptService.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
newPrompt.Should().NotBeNull();
|
|
// Note: In a real scenario, we might mock the file system to test cache clearing
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSystemPromptAsync_ShouldReturnDefaultPrompt_WhenFileNotFound()
|
|
{
|
|
// Arrange
|
|
var aiSettings = new AISettings { SystemPromptPath = "nonexistent-file.txt" };
|
|
var aiSettingsMock = TestDataBuilder.Mocks.CreateOptionsMock(aiSettings);
|
|
var service = new SystemPromptService(_loggerMock.Object, aiSettingsMock.Object);
|
|
|
|
// Act
|
|
var result = await service.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
result.Should().Be(SystemPromptService.DefaultPrompt);
|
|
_loggerMock.Verify(
|
|
x =>
|
|
x.Log(
|
|
LogLevel.Warning,
|
|
It.IsAny<EventId>(),
|
|
It.Is<It.IsAnyType>(
|
|
(v, t) => v.ToString()!.Contains("System prompt file not found")
|
|
),
|
|
It.IsAny<Exception>(),
|
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
|
),
|
|
Times.Once
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSystemPromptAsync_ShouldReturnDefaultPrompt_WhenFileReadFails()
|
|
{
|
|
// Arrange
|
|
var aiSettings = new AISettings
|
|
{
|
|
SystemPromptPath = "invalid-path-that-causes-exception.txt",
|
|
};
|
|
var aiSettingsMock = TestDataBuilder.Mocks.CreateOptionsMock(aiSettings);
|
|
var service = new SystemPromptService(_loggerMock.Object, aiSettingsMock.Object);
|
|
|
|
// Act
|
|
var result = await service.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
result.Should().Be(SystemPromptService.DefaultPrompt);
|
|
// The file doesn't exist, so it logs a warning, not an error
|
|
_loggerMock.Verify(
|
|
x =>
|
|
x.Log(
|
|
LogLevel.Warning,
|
|
It.IsAny<EventId>(),
|
|
It.Is<It.IsAnyType>(
|
|
(v, t) => v.ToString()!.Contains("System prompt file not found")
|
|
),
|
|
It.IsAny<Exception>(),
|
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
|
),
|
|
Times.Once
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSystemPromptAsync_ShouldReturnDefaultPrompt_WhenPathIsNull()
|
|
{
|
|
// Arrange
|
|
var aiSettings = new AISettings { SystemPromptPath = null! };
|
|
var aiSettingsMock = TestDataBuilder.Mocks.CreateOptionsMock(aiSettings);
|
|
var service = new SystemPromptService(_loggerMock.Object, aiSettingsMock.Object);
|
|
|
|
// Act
|
|
var result = await service.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
result.Should().Be(SystemPromptService.DefaultPrompt);
|
|
_loggerMock.Verify(
|
|
x =>
|
|
x.Log(
|
|
LogLevel.Error,
|
|
It.IsAny<EventId>(),
|
|
It.Is<It.IsAnyType>(
|
|
(v, t) => v.ToString()!.Contains("Failed to load system prompt")
|
|
),
|
|
It.IsAny<Exception>(),
|
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
|
),
|
|
Times.Once
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSystemPromptAsync_ShouldReturnDefaultPrompt_WhenPathIsEmpty()
|
|
{
|
|
// Arrange
|
|
var aiSettings = new AISettings { SystemPromptPath = string.Empty };
|
|
var aiSettingsMock = TestDataBuilder.Mocks.CreateOptionsMock(aiSettings);
|
|
var service = new SystemPromptService(_loggerMock.Object, aiSettingsMock.Object);
|
|
|
|
// Act
|
|
var result = await service.GetSystemPromptAsync();
|
|
|
|
// Assert
|
|
result.Should().Be(SystemPromptService.DefaultPrompt);
|
|
// Empty path results in file not found, so it logs a warning, not an error
|
|
_loggerMock.Verify(
|
|
x =>
|
|
x.Log(
|
|
LogLevel.Warning,
|
|
It.IsAny<EventId>(),
|
|
It.Is<It.IsAnyType>(
|
|
(v, t) => v.ToString()!.Contains("System prompt file not found")
|
|
),
|
|
It.IsAny<Exception>(),
|
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
|
),
|
|
Times.Once
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ReloadPromptAsync_ShouldClearCacheAndReload()
|
|
{
|
|
// Arrange
|
|
var aiSettings = new AISettings { SystemPromptPath = "nonexistent-file.txt" };
|
|
var aiSettingsMock = TestDataBuilder.Mocks.CreateOptionsMock(aiSettings);
|
|
var service = new SystemPromptService(_loggerMock.Object, aiSettingsMock.Object);
|
|
|
|
// Act
|
|
await service.GetSystemPromptAsync(); // First call to cache default prompt
|
|
await service.ReloadPromptAsync(); // Reload should clear cache
|
|
|
|
// Assert
|
|
// The service should still return the default prompt after reload
|
|
var result = await service.GetSystemPromptAsync();
|
|
result.Should().Be(SystemPromptService.DefaultPrompt);
|
|
}
|
|
}
|