Files
ChatBot/ChatBot.Tests/Program/ProgramConfigurationTests.cs
Leonid Pershin 1c910d7b7f
All checks were successful
SonarQube / Build and analyze (push) Successful in 3m54s
Unit Tests / Run Tests (push) Successful in 2m23s
add tests
2025-10-20 15:11:42 +03:00

366 lines
16 KiB
C#

using ChatBot.Data;
using ChatBot.Models.Configuration;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace ChatBot.Tests.Program;
public class ProgramConfigurationTests
{
[Fact]
public void Configuration_ShouldHaveValidSettings()
{
// Arrange
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
{ "TelegramBot:BotToken", "1234567890123456789012345678901234567890" },
{ "Ollama:Url", "http://localhost:11434" },
{ "Ollama:DefaultModel", "llama3" },
{ "AI:CompressionThreshold", "100" },
{
"Database:ConnectionString",
"Host=localhost;Port=5432;Database=test;Username=test;Password=test"
},
{ "Database:CommandTimeout", "30" },
{ "Database:EnableSensitiveDataLogging", "false" },
}
)
.Build();
// Act
var telegramSettings = configuration.GetSection("TelegramBot").Get<TelegramBotSettings>();
var ollamaSettings = configuration.GetSection("Ollama").Get<OllamaSettings>();
var aiSettings = configuration.GetSection("AI").Get<AISettings>();
var databaseSettings = configuration.GetSection("Database").Get<DatabaseSettings>();
// Assert
telegramSettings.Should().NotBeNull();
telegramSettings!.BotToken.Should().Be("1234567890123456789012345678901234567890");
ollamaSettings.Should().NotBeNull();
ollamaSettings!.Url.Should().Be("http://localhost:11434");
ollamaSettings.DefaultModel.Should().Be("llama3");
aiSettings.Should().NotBeNull();
aiSettings!.CompressionThreshold.Should().Be(100);
databaseSettings.Should().NotBeNull();
databaseSettings!
.ConnectionString.Should()
.Be("Host=localhost;Port=5432;Database=test;Username=test;Password=test");
databaseSettings.CommandTimeout.Should().Be(30);
databaseSettings.EnableSensitiveDataLogging.Should().BeFalse();
}
[Fact]
public void EnvironmentVariableOverrides_ShouldWorkCorrectly()
{
// Arrange
Environment.SetEnvironmentVariable(
"TELEGRAM_BOT_TOKEN",
"env-token-1234567890123456789012345678901234567890"
);
Environment.SetEnvironmentVariable("OLLAMA_URL", "http://env-ollama:11434");
Environment.SetEnvironmentVariable("OLLAMA_DEFAULT_MODEL", "env-model");
Environment.SetEnvironmentVariable("DB_HOST", "env-host");
Environment.SetEnvironmentVariable("DB_PORT", "5433");
Environment.SetEnvironmentVariable("DB_NAME", "env-db");
Environment.SetEnvironmentVariable("DB_USER", "env-user");
Environment.SetEnvironmentVariable("DB_PASSWORD", "env-password");
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
{
"TelegramBot:BotToken",
"config-token-1234567890123456789012345678901234567890"
},
{ "Ollama:Url", "http://config-ollama:11434" },
{ "Ollama:DefaultModel", "config-model" },
{
"Database:ConnectionString",
"Host=config-host;Port=5432;Database=config-db;Username=config-user;Password=config-password"
},
}
)
.AddEnvironmentVariables()
.Build();
// Act - Simulate the environment variable override logic from Program.cs
var telegramSettings = new TelegramBotSettings();
configuration.GetSection("TelegramBot").Bind(telegramSettings);
telegramSettings.BotToken =
Environment.GetEnvironmentVariable("TELEGRAM_BOT_TOKEN") ?? telegramSettings.BotToken;
var ollamaSettings = new OllamaSettings();
configuration.GetSection("Ollama").Bind(ollamaSettings);
ollamaSettings.Url = Environment.GetEnvironmentVariable("OLLAMA_URL") ?? ollamaSettings.Url;
ollamaSettings.DefaultModel =
Environment.GetEnvironmentVariable("OLLAMA_DEFAULT_MODEL")
?? ollamaSettings.DefaultModel;
var databaseSettings = new DatabaseSettings();
configuration.GetSection("Database").Bind(databaseSettings);
var host = Environment.GetEnvironmentVariable("DB_HOST") ?? "localhost";
var port = Environment.GetEnvironmentVariable("DB_PORT") ?? "5432";
var name = Environment.GetEnvironmentVariable("DB_NAME") ?? "chatbot";
var user = Environment.GetEnvironmentVariable("DB_USER") ?? "postgres";
var password = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? "postgres";
databaseSettings.ConnectionString =
$"Host={host};Port={port};Database={name};Username={user};Password={password}";
// Assert
telegramSettings
.BotToken.Should()
.Be("env-token-1234567890123456789012345678901234567890");
ollamaSettings.Url.Should().Be("http://env-ollama:11434");
ollamaSettings.DefaultModel.Should().Be("env-model");
databaseSettings
.ConnectionString.Should()
.Be("Host=env-host;Port=5433;Database=env-db;Username=env-user;Password=env-password");
// Cleanup
Environment.SetEnvironmentVariable("TELEGRAM_BOT_TOKEN", null);
Environment.SetEnvironmentVariable("OLLAMA_URL", null);
Environment.SetEnvironmentVariable("OLLAMA_DEFAULT_MODEL", null);
Environment.SetEnvironmentVariable("DB_HOST", null);
Environment.SetEnvironmentVariable("DB_PORT", null);
Environment.SetEnvironmentVariable("DB_NAME", null);
Environment.SetEnvironmentVariable("DB_USER", null);
Environment.SetEnvironmentVariable("DB_PASSWORD", null);
}
[Fact]
public void EnvironmentVariableFallbacks_ShouldUseConfigWhenEnvMissing()
{
// Arrange: ensure env vars are not set
Environment.SetEnvironmentVariable("TELEGRAM_BOT_TOKEN", null);
Environment.SetEnvironmentVariable("OLLAMA_URL", null);
Environment.SetEnvironmentVariable("OLLAMA_DEFAULT_MODEL", null);
Environment.SetEnvironmentVariable("DB_HOST", null);
Environment.SetEnvironmentVariable("DB_PORT", null);
Environment.SetEnvironmentVariable("DB_NAME", null);
Environment.SetEnvironmentVariable("DB_USER", null);
Environment.SetEnvironmentVariable("DB_PASSWORD", null);
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
{
"TelegramBot:BotToken",
"config-token-0000000000000000000000000000000000000000"
},
{ "Ollama:Url", "http://config-ollama:11434" },
{ "Ollama:DefaultModel", "config-model" },
{
"Database:ConnectionString",
"Host=config-host;Port=5432;Database=config-db;Username=config-user;Password=config-password"
},
}
)
.Build();
// Act - Simulate Program.cs binding and env override logic
var telegramSettings = new TelegramBotSettings();
configuration.GetSection("TelegramBot").Bind(telegramSettings);
telegramSettings.BotToken =
Environment.GetEnvironmentVariable("TELEGRAM_BOT_TOKEN") ?? telegramSettings.BotToken;
var ollamaSettings = new OllamaSettings();
configuration.GetSection("Ollama").Bind(ollamaSettings);
ollamaSettings.Url = Environment.GetEnvironmentVariable("OLLAMA_URL") ?? ollamaSettings.Url;
ollamaSettings.DefaultModel =
Environment.GetEnvironmentVariable("OLLAMA_DEFAULT_MODEL")
?? ollamaSettings.DefaultModel;
var databaseSettings = new DatabaseSettings();
configuration.GetSection("Database").Bind(databaseSettings);
var host = Environment.GetEnvironmentVariable("DB_HOST") ?? "localhost";
var port = Environment.GetEnvironmentVariable("DB_PORT") ?? "5432";
var name = Environment.GetEnvironmentVariable("DB_NAME") ?? "chatbot";
var user = Environment.GetEnvironmentVariable("DB_USER") ?? "postgres";
var password = Environment.GetEnvironmentVariable("DB_PASSWORD") ?? "postgres";
var expectedConnectionString =
$"Host={host};Port={port};Database={name};Username={user};Password={password}";
databaseSettings.ConnectionString =
$"Host={host};Port={port};Database={name};Username={user};Password={password}";
// Assert - values should remain from configuration when env vars are missing
telegramSettings
.BotToken.Should()
.Be("config-token-0000000000000000000000000000000000000000");
ollamaSettings.Url.Should().Be("http://config-ollama:11434");
ollamaSettings.DefaultModel.Should().Be("config-model");
// Because our fallback block reconstructs from env with defaults when missing,
// ensure it equals the configuration's original connection string when all envs are missing
databaseSettings.ConnectionString.Should().Be(expectedConnectionString);
}
[Fact]
public void DatabaseContext_ShouldBeConfiguredCorrectly()
{
// Arrange
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
{
"Database:ConnectionString",
"Host=localhost;Port=5432;Database=test;Username=test;Password=test"
},
{ "Database:CommandTimeout", "60" },
{ "Database:EnableSensitiveDataLogging", "true" },
}
)
.Build();
services.AddSingleton<IConfiguration>(configuration);
services.Configure<DatabaseSettings>(configuration.GetSection("Database"));
// Act
services.AddDbContext<ChatBotDbContext>(
(serviceProvider, options) =>
{
var dbSettings = serviceProvider
.GetRequiredService<IOptions<DatabaseSettings>>()
.Value;
options.UseInMemoryDatabase("test-db");
if (dbSettings.EnableSensitiveDataLogging)
{
options.EnableSensitiveDataLogging();
}
}
);
var serviceProvider = services.BuildServiceProvider();
var context = serviceProvider.GetRequiredService<ChatBotDbContext>();
// Assert
context.Should().NotBeNull();
context.Database.Should().NotBeNull();
context.ChatSessions.Should().NotBeNull();
context.ChatMessages.Should().NotBeNull();
}
[Fact]
public void ServiceRegistration_ShouldWorkWithoutValidation()
{
// Arrange
var services = new ServiceCollection();
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
{ "TelegramBot:BotToken", "1234567890123456789012345678901234567890" },
{ "Ollama:Url", "http://localhost:11434" },
{ "Ollama:DefaultModel", "llama3" },
{ "AI:CompressionThreshold", "100" },
{
"Database:ConnectionString",
"Host=localhost;Port=5432;Database=test;Username=test;Password=test"
},
{ "Database:CommandTimeout", "30" },
{ "Database:EnableSensitiveDataLogging", "false" },
}
)
.Build();
// Act - Register services without validation
services.AddSingleton<IConfiguration>(configuration);
services.AddLogging();
services.Configure<TelegramBotSettings>(configuration.GetSection("TelegramBot"));
services.Configure<OllamaSettings>(configuration.GetSection("Ollama"));
services.Configure<AISettings>(configuration.GetSection("AI"));
services.Configure<DatabaseSettings>(configuration.GetSection("Database"));
services.AddDbContext<ChatBotDbContext>(
(serviceProvider, options) =>
{
options.UseInMemoryDatabase("test-db");
}
);
var serviceProvider = services.BuildServiceProvider();
// Assert - Check that configuration services are registered
serviceProvider.GetRequiredService<IOptions<TelegramBotSettings>>().Should().NotBeNull();
serviceProvider.GetRequiredService<IOptions<OllamaSettings>>().Should().NotBeNull();
serviceProvider.GetRequiredService<IOptions<AISettings>>().Should().NotBeNull();
serviceProvider.GetRequiredService<IOptions<DatabaseSettings>>().Should().NotBeNull();
serviceProvider.GetRequiredService<ChatBotDbContext>().Should().NotBeNull();
}
[Fact]
public void ConfigurationSections_ShouldBeAccessible()
{
// Arrange
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(
new Dictionary<string, string?>
{
{ "TelegramBot:BotToken", "1234567890123456789012345678901234567890" },
{ "Ollama:Url", "http://localhost:11434" },
{ "AI:CompressionThreshold", "100" },
{
"Database:ConnectionString",
"Host=localhost;Port=5432;Database=test;Username=test;Password=test"
},
}
)
.Build();
// Act & Assert
configuration.GetSection("TelegramBot").Should().NotBeNull();
configuration.GetSection("Ollama").Should().NotBeNull();
configuration.GetSection("AI").Should().NotBeNull();
configuration.GetSection("Database").Should().NotBeNull();
configuration
.GetSection("TelegramBot")["BotToken"]
.Should()
.Be("1234567890123456789012345678901234567890");
configuration.GetSection("Ollama")["Url"].Should().Be("http://localhost:11434");
configuration.GetSection("AI")["CompressionThreshold"].Should().Be("100");
configuration
.GetSection("Database")["ConnectionString"]
.Should()
.Be("Host=localhost;Port=5432;Database=test;Username=test;Password=test");
}
[Fact]
public void DatabaseContext_ShouldHaveCorrectEntityTypes()
{
// Arrange
var services = new ServiceCollection();
services.AddDbContext<ChatBotDbContext>(options => options.UseInMemoryDatabase("test-db"));
var serviceProvider = services.BuildServiceProvider();
var context = serviceProvider.GetRequiredService<ChatBotDbContext>();
// Act
var model = context.Model;
// Assert
var chatSessionEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatSessionEntity)
);
var chatMessageEntity = model.FindEntityType(
typeof(ChatBot.Models.Entities.ChatMessageEntity)
);
chatSessionEntity.Should().NotBeNull();
chatMessageEntity.Should().NotBeNull();
chatSessionEntity!.GetTableName().Should().Be("chat_sessions");
chatMessageEntity!.GetTableName().Should().Be("chat_messages");
}
}