Fluent Validation - Unit Tests
Fluent Validation - Unit Tests

Fluent Validation – Unit Testing the Validators

Business rules can be complicated and hence it becomes immensely important to automate the testing of those rules. The library, Fluent Validation, provides APIs to support the automated testing of the rules. In this article, we are going to have a look at how to unit test the validation logic written using fluent validation.

Before we begin !

I have been writing about the fluent validation library and below is the list of all the articles that I have published. I would recommend going through this list before coming to the unit testing part.

Scenario

We are going to use the same scenario that I discussed in one of the previous posts.

Let’s say we have an entity, Student. It has properties – IdName, and Version, here Id is basically to uniquely identify the record. For calling AddStudent endpoint, id should be always zero, but for calling UpdateStudent endpoint, id should not be zero.

The Version property is supposed to be used in update endpoint. It is to avoid overwriting more recent version of the record. So, Version should be non-zero while calling update endpoint and it should be zero while calling Add endpoint.

Article about RuleSets

Then in the previous article, we created 5 different validators for validating properties from Student class. Then these validators were used to compose another 2 validators.

  • StudentWithIdValidator, to check that Id should be greater than zero
  • StudentWithoutIdValidator, to check that Id should be equal to zero
  • StudentWithVersionValidator, to check that Version should be greater than zero
  • StudentWithoutVersionValidator, to check that Version should be equal to zero
  • StudentNameValidator, to apply validations to Name property
  • AddStudentValidator, which contains validators combined for AddStudent endpoint. This validator should be triggered from the add endpoint.
  • UpdateStudentValidator, which contains validators combined together for UpdateStudent endpoint. This validator should be triggered from the update endpoint.

The code snippet given below shows the code for these validators.

Create Unit Test Project

Let’s create a xUnit test project in the same solution where the API project containing above mentioned validators is located. Once the test project is created, add reference of the API project in the test project.

FluentValidation.TestHelper

This is a namespace in the Fluent Validation library. This namespace provides a method TestValidate (or TestValidateAsync) method. This method should be used for testing purposes. This method returns a result, TestValidationResult, on which we can perform assertions.

There are two important assertion methods:

  • ShouldHaveValidationErrorFor
  • ShouldNotHaveValidationErrorFor

These methods take expressions as input, where we can specify the property, for which the validation has failed (or passed).

There are two more methods. We can use WithErrorMessage to verify that the error message also matches. And we want to make sure that there are no other errors apart from ones specified in the assertion, then we can also use the method, Only.

A Sample Unit Test

Let’s create a class student validator and let’s add tests for two scenarios.

  • When Id is non-zero, version is zero and name has more than 10 characters, then the AddStudentValidator validation should fail for Id property.
  • When Id is non-zero, version is zero and name has more than 10 characters, then UpdateStudentValidator validation should fail for Version property.

As you can see in the code snippet given below, we have used assertion methods mentioned above to validate the validators. I hope this example should give fair idea about how the validators can be tested.

Points to Remember

If validators has asynchronous logic, then it is better to use TestValidateAsync. Another thing is, when we are testing the types which are dependent on validators (e.g. controllers in our example), it is better to not mock the validator. We can mock the dependencies of validator if they have any.

I hope you find this information helpful. Let me know your thoughts.

Leave a ReplyCancel reply