335 lines
10 KiB
C#
335 lines
10 KiB
C#
using ChatBot.Models.Configuration;
|
|
using ChatBot.Models.Configuration.Validators;
|
|
using FluentAssertions;
|
|
using FluentValidation.TestHelper;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace ChatBot.Tests.Configuration.Validators;
|
|
|
|
public class DatabaseSettingsValidatorTests
|
|
{
|
|
private readonly DatabaseSettingsValidator _validator;
|
|
|
|
public DatabaseSettingsValidatorTests()
|
|
{
|
|
_validator = new DatabaseSettingsValidator();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithValidSettings_ShouldReturnSuccess()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeTrue();
|
|
result.Failed.Should().BeFalse();
|
|
result.FailureMessage.Should().BeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithEmptyConnectionString_ShouldReturnFailure()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.ConnectionString = string.Empty;
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result.FailureMessage.Should().Contain("Database connection string is required");
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithNullConnectionString_ShouldReturnFailure()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.ConnectionString = null!;
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result.FailureMessage.Should().Contain("Database connection string is required");
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithWhitespaceConnectionString_ShouldReturnFailure()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.ConnectionString = " ";
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result.FailureMessage.Should().Contain("Database connection string is required");
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(0)]
|
|
[InlineData(-1)]
|
|
[InlineData(-10)]
|
|
public void Validate_WithInvalidCommandTimeout_ShouldReturnFailure(int commandTimeout)
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.CommandTimeout = commandTimeout;
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result.FailureMessage.Should().Contain("Command timeout must be greater than 0");
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(301)]
|
|
[InlineData(500)]
|
|
[InlineData(1000)]
|
|
public void Validate_WithTooHighCommandTimeout_ShouldReturnFailure(int commandTimeout)
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.CommandTimeout = commandTimeout;
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result
|
|
.FailureMessage.Should()
|
|
.Contain("Command timeout must be less than or equal to 300 seconds");
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1)]
|
|
[InlineData(30)]
|
|
[InlineData(300)]
|
|
public void Validate_WithValidCommandTimeout_ShouldReturnSuccess(int commandTimeout)
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.CommandTimeout = commandTimeout;
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeTrue();
|
|
result.Failed.Should().BeFalse();
|
|
result.FailureMessage.Should().BeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithValidConnectionString_ShouldReturnSuccess()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.ConnectionString =
|
|
"Host=localhost;Port=5432;Database=test;Username=user;Password=pass";
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeTrue();
|
|
result.Failed.Should().BeFalse();
|
|
result.FailureMessage.Should().BeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithMultipleValidationErrors_ShouldReturnAllErrors()
|
|
{
|
|
// Arrange
|
|
var settings = new DatabaseSettings
|
|
{
|
|
ConnectionString = string.Empty, // Invalid
|
|
CommandTimeout = 0, // Invalid
|
|
EnableSensitiveDataLogging = false,
|
|
};
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result.FailureMessage.Should().Contain("Database connection string is required");
|
|
result.FailureMessage.Should().Contain("Command timeout must be greater than 0");
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_WithNullSettings_ShouldThrowException()
|
|
{
|
|
// Arrange & Act & Assert
|
|
var act = () => _validator.Validate(null, null!);
|
|
act.Should()
|
|
.Throw<InvalidOperationException>()
|
|
.WithMessage(
|
|
"Cannot pass a null model to Validate/ValidateAsync. The root model must be non-null."
|
|
);
|
|
}
|
|
|
|
[Fact]
|
|
public void FluentValidation_ConnectionString_ShouldHaveCorrectRule()
|
|
{
|
|
// Arrange
|
|
var settings = new DatabaseSettings { ConnectionString = string.Empty };
|
|
|
|
// Act & Assert
|
|
var result = _validator.TestValidate(settings);
|
|
result
|
|
.ShouldHaveValidationErrorFor(x => x.ConnectionString)
|
|
.WithErrorMessage("Database connection string is required");
|
|
}
|
|
|
|
[Fact]
|
|
public void FluentValidation_CommandTimeout_ShouldHaveCorrectRules()
|
|
{
|
|
// Arrange
|
|
var settings = new DatabaseSettings { CommandTimeout = 0 };
|
|
|
|
// Act & Assert
|
|
var result = _validator.TestValidate(settings);
|
|
result
|
|
.ShouldHaveValidationErrorFor(x => x.CommandTimeout)
|
|
.WithErrorMessage("Command timeout must be greater than 0");
|
|
}
|
|
|
|
[Fact]
|
|
public void FluentValidation_CommandTimeoutTooHigh_ShouldHaveCorrectRule()
|
|
{
|
|
// Arrange
|
|
var settings = new DatabaseSettings { CommandTimeout = 301 };
|
|
|
|
// Act & Assert
|
|
var result = _validator.TestValidate(settings);
|
|
result
|
|
.ShouldHaveValidationErrorFor(x => x.CommandTimeout)
|
|
.WithErrorMessage("Command timeout must be less than or equal to 300 seconds");
|
|
}
|
|
|
|
[Fact]
|
|
public void FluentValidation_ValidSettings_ShouldNotHaveErrors()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
|
|
// Act & Assert
|
|
var result = _validator.TestValidate(settings);
|
|
result.ShouldNotHaveAnyValidationErrors();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("Host=localhost;Port=5432;Database=test;Username=user;Password=pass")]
|
|
[InlineData("Server=localhost;Database=test;User Id=user;Password=pass")]
|
|
[InlineData("Data Source=localhost;Initial Catalog=test;User ID=user;Password=pass")]
|
|
public void FluentValidation_ValidConnectionStrings_ShouldNotHaveErrors(string connectionString)
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.ConnectionString = connectionString;
|
|
|
|
// Act & Assert
|
|
var result = _validator.TestValidate(settings);
|
|
result.ShouldNotHaveValidationErrorFor(x => x.ConnectionString);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1)]
|
|
[InlineData(5)]
|
|
[InlineData(30)]
|
|
[InlineData(60)]
|
|
[InlineData(120)]
|
|
[InlineData(300)]
|
|
public void FluentValidation_ValidCommandTimeouts_ShouldNotHaveErrors(int commandTimeout)
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
settings.CommandTimeout = commandTimeout;
|
|
|
|
// Act & Assert
|
|
var result = _validator.TestValidate(settings);
|
|
result.ShouldNotHaveValidationErrorFor(x => x.CommandTimeout);
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidateOptionsResult_Success_ShouldHaveCorrectProperties()
|
|
{
|
|
// Arrange
|
|
var settings = CreateValidDatabaseSettings();
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeTrue();
|
|
result.Failed.Should().BeFalse();
|
|
result.FailureMessage.Should().BeNullOrEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void ValidateOptionsResult_Failure_ShouldHaveCorrectProperties()
|
|
{
|
|
// Arrange
|
|
var settings = new DatabaseSettings { ConnectionString = string.Empty, CommandTimeout = 0 };
|
|
|
|
// Act
|
|
var result = _validator.Validate(null, settings);
|
|
|
|
// Assert
|
|
result.Succeeded.Should().BeFalse();
|
|
result.Failed.Should().BeTrue();
|
|
result.FailureMessage.Should().NotBeNullOrEmpty();
|
|
result.FailureMessage.Should().Contain("Database connection string is required");
|
|
result.FailureMessage.Should().Contain("Command timeout must be greater than 0");
|
|
}
|
|
|
|
[Fact]
|
|
public void Validator_ShouldImplementIValidateOptions()
|
|
{
|
|
// Arrange & Act
|
|
var validator = new DatabaseSettingsValidator();
|
|
|
|
// Assert
|
|
validator.Should().BeAssignableTo<IValidateOptions<DatabaseSettings>>();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validator_ShouldInheritFromAbstractValidator()
|
|
{
|
|
// Arrange & Act
|
|
var validator = new DatabaseSettingsValidator();
|
|
|
|
// Assert
|
|
validator.Should().BeAssignableTo<FluentValidation.AbstractValidator<DatabaseSettings>>();
|
|
}
|
|
|
|
private static DatabaseSettings CreateValidDatabaseSettings()
|
|
{
|
|
return new DatabaseSettings
|
|
{
|
|
ConnectionString = "Host=localhost;Port=5432;Database=test;Username=test;Password=test",
|
|
CommandTimeout = 30,
|
|
EnableSensitiveDataLogging = false,
|
|
};
|
|
}
|
|
}
|