Testowanie reguł walidacyjnych w FluentValidation

Walidacja danych w aplikacjach .NET jest kluczowa dla zapewnienia jakości i bezpieczeństwa oprogramowania. FluentValidation, w połączeniu z XUnit, oferuje wydajne narzędzia do definiowania i testowania reguł walidacyjnych. W tym artykule omówimy, jak testować reguły walidacyjne przy użyciu tych technologii, koncentrując się na konkretnych przykładach.

Rozpocznijmy od prostego walidatora dla modelu User, który wymaga, aby użytkownik podał swoje imię oraz adres email. Reguły walidacyjne, takie jak NotEmpty dla imienia oraz EmailAddress dla pola email, pomagają zapewnić, że dane wejściowe są zarówno kompletne, jak i prawidłowe.

Przykładowy walidator może wyglądać tak:

public class UserValidator : AbstractValidator<User> {
    public UserValidator() {
        RuleFor(user => user.Name).NotEmpty().WithMessage("Name is required.");
        RuleFor(user => user.Email).EmailAddress().WithMessage("Invalid email address.");
    }
}

Testowanie reguł walidacyjnych

Testowanie walidatora wymaga przemyślanego podejścia, gdzie każdy test jednostkowy koncentruje się na specyficznym aspekcie walidacji. Przykładowo, możemy sprawdzić, czy pole Name nie jest puste, inicjalizując obiekt User z pustym imieniem, uruchamiając walidator i sprawdzając, czy walidator poprawnie zidentyfikował błąd. Poniższy test sprawdza, czy walidator identyfikuje pustą wartość Name jako błąd:

[Fact]
public void Should_have_error_when_Name_is_empty() {
    // Arrange
    var validator = new UserValidator();
    var user = new User { Name = string.Empty, Email = "test@example.com" };

    // Act
    var result = validator.TestValidate(user);

    // Assert
    result.ShouldHaveValidationErrorFor(user => user.Name).WithErrorMessage("Name is required.");
}

W teście tworzymy instancję walidatora, definiujemy użytkownika z pustym imieniem, uruchamiamy walidator i za pomocą metody ShouldHaveValidationErrorFor sprawdzamy, czy walidator zwrócił oczekiwany błąd walidacji.

Metoda TestValidate w FluentValidation służy do uruchamiania walidatora w celach testowych, umożliwiając przeprowadzenie asercji na wyniku walidacji. Jest to przydatne narzędzie do testowania, które pozwala na traktowanie walidatorów jako "czarnych skrzynek" - dostarczamy dane wejściowe i sprawdzamy, czy wyniki walidacji są poprawne. Metoda TestValidate posiada również asynchroniczny odpowiednik TestValidateAsync, który działa podobnie, ale zwraca zadanie (Task), co jest przydatne w testach asynchronicznych. Dzięki TestValidate programiści mogą łatwo i efektywnie weryfikować działanie reguł walidacyjnych w swoich aplikacjach.

Równie ważne jest upewnienie się, że walidator nie generuje błędów dla poprawnych danych. Przykład poniżej pokazuje, jak upewnić się, że poprawny adres email nie powoduje błędów walidacji:

[Fact]
public void Should_not_have_error_when_Email_is_valid() {
    // Arrange
    var validator = new UserValidator();
    var user = new User { Name = "Jan Kowalski", Email = "valid@example.com" };

    // Act
    var result = validator.TestValidate(user);

    // Assert
    result.ShouldNotHaveValidationErrorFor(user => user.Email);
}

Test ten inicjalizuje walidator i użytkownika z prawidłowym adresem email, a następnie używa metody ShouldNotHaveValidationErrorFor, aby upewnić się, że dla pola Email nie pojawi się żaden błąd walidacji.

Metoda Only

Metoda Only w FluentValidation jest używana, aby upewnić się, że nie wystąpiły żadne inne błędy walidacyjne poza określonymi w warunkach. Na przykład:

[Fact]
public void Should_have_error_when_Name_is_empty() {
    // Arrange
    var validator = new UserValidator();
    var user = new User { Name = string.Empty, Email = "test@example.com" };

    // Act
    var result = validator.TestValidate(user);

    // Assert
    result.ShouldHaveValidationErrorFor(user => user.Name).WithErrorMessage("Name is required.").Only();
}

Metoda Only sprawdza, że jedynymi błędami walidacyjnymi są te, które określiliśmy w warunkach. Jeśli pojawią się inne błędy, test zakończy się niepowodzeniem. Jest to przydatne, gdy chcemy mieć pewność, że nasza walidacja zwraca dokładnie takie błędy, jakich się spodziewamy, bez żadnych dodatkowych niespodzianek.

Podsumowanie

Testowanie reguł walidacyjnych z użyciem FluentValidation i XUnit pozwala programistom na precyzyjne sprawdzanie i zapewnienie jakości danych wejściowych w aplikacji. Metody takie jak ShouldHaveValidationErrorFor i ShouldNotHaveValidationErrorFor są kluczowe dla upewnienia się, że walidatory działają poprawnie, wykrywają błędy tam, gdzie powinny, i nie generują fałszywych alarmów. Dzięki temu możemy zapewnić niezawodność i bezpieczeństwo naszych aplikacji.

Do zobaczenia w następnych postach.