From TDD to DDD: Building a .NET Core Web API - Part 5
Tags: tdd, ddd, netcore, xunit
Published: 2019-12-16 12:23:09

The complete project can be found here: [https://github.com/lucianopereira86/CRUD-NetCore-TDD](https://github.com/lucianopereira86/CRUD-NetCore-TDD)

## Technologies

- [Visual Studio 2019](https://visualstudio.microsoft.com/pt-br/downloads/)
- [.NET Core 3.1.0](https://dotnet.microsoft.com/download/dotnet-core/3.1)
- [xUnit 2.4.0](https://www.nuget.org/packages/xunit/2.4.0)
- [Microsoft.EntityFrameworkCore 3.1.0](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore/3.1.0)
- [FluentValidation 8.6.0](https://www.nuget.org/packages/fluentvalidation)

## Topics
- [Post User • Theory](#post-user-theory)
      - [Red Step • Name](#post-user-theory-red-step-name)
      - [Green Step • Name](#post-user-theory-green-step-name)

## Post User • Theory

### Red Step • Name

The **Theory** must be used to test the INVALID values from an entity. Some VALID values might be used as well but only to confirm that the test works perfectly for what it was designed for.  
Let's start testing the possible values for the User's "Name" attribute.  
Inside the "PostUserTest" class write the following code:

```cs
#region THEORY
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ")]
[InlineData("LUCIANO PEREIRA")]
public void Theory_PostUser_Name (string Name)
{
    var user = new User
    {
        Name = Name
    };
    Assert.Null(user.Name);
    Assert.Empty(user.Name);
    Assert.True(user.Name.Length > 20);
}

#endregion
```

The "Name" will be invalid if it be null, empty or exceeds 20 characters.
If you run the test, this will the result:

![print09](https://thepracticaldev.s3.amazonaws.com/i/8fglnv4saalrkxrfhso8.JPG)

The errors happened because all the conditions weren't respected at once. They should be tested separetely in different methods, but as the User class has many attributes, it would consume lots of lines of code and, most important, time.  
To improve our development, we must use the "FluentValidation" package. It contains many functions that validate entire objects or attributes and return all the errors in a list.  
Before doing it, rename the "Theory_PostUser_Name" method to "Theory_PostUser_Name_NoValidation" and change the code a bit:

```cs
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ")]
[InlineData("LUCIANO PEREIRA")]
public void Theory_PostUser_Name_NoValidation (string Name)
{
    var user = new User
    {
        Name = Name
    };

    var val = new PostUserValidator().Validate(user);
    Assert.False(val.IsValid);
}
```

All the validations will be implemented inside the "PostUserValidator" class. If one condition be disrespected, than the "val.IsValid" attribute will be false. It's time to go to the **Green** step.

### Green Step • Name

Inside the Infra project, install the "FluentValidation" package through Nuget, create a folder named "Validations" and add into it a file named "PostUserValidator.cs". It will be responsible for validating only the "User" class attributes required in the POST method.

```cs
using CRUD_NETCore_TDD.Infra.Models;
using FluentValidation;

namespace CRUD_NETCore_TDD.Infra.Validations
{
    public class PostUserValidator: AbstractValidator<User>
    {
        public PostUserValidator()
        {
            RuleFor(x => x.Name)
                .Cascade(CascadeMode.StopOnFirstFailure)
                .NotEmpty()
                .MaximumLength(20);
        }
    }
}
```

Inside this code, the "Name" attribute must respect some rules.
The "Cascade(CascadeMode.StopOnFirstFailure)" means that if an error be encountered, it should return immediately from the field validation.  
"NotEmpty" means that it should not be null or empty.  
"MaximumLength" means that it should not have more than 20 characters.  
These are the same rules we have stablished before.

Now, go back to the "PostUserTest" class, copy the "Theory_PostUser_Name_NoValidation" method, comment the original, rename the copy to "Theory_PostUser_Name_Validation" and import the "PostUserValidator" class. The file will be able to compile.

Run the test again and this will be the result:

![print10](https://thepracticaldev.s3.amazonaws.com/i/1l6qjlzrarxuvatlap1a.JPG)

| ATTENTION |
| --- |
| The **Green** tests should have full green results to prove that all the validations have run correctly. But as a practice of mine, I put at least one valid value to show a red result as a safety measure. In no other way this approach should be used because it violates the TDD principles of the **Green** step.|

All the conditions have been met except for the one containing a valid value ("LUCIANO PEREIRA") which was to be expected. So we can comment its line for further tests.  

## Next 

But there is still a problem... How to prove that an specific condition was met instead of another one?  
We will solve this but adding error codes for each one. Time for refactoring...