LUCIANO DE SOUSA PEREIRA
Posted on December 16, 2019
The complete project can be found here: https://github.com/lucianopereira86/CRUD-NetCore-TDD
Technologies
- Visual Studio 2019
- .NET Core 3.1.0
- xUnit 2.4.0
- Microsoft.EntityFrameworkCore 3.1.0
- FluentValidation 8.6.0
Post User • Fact
Green Step
Create a folder named "Models" inside the Infra project with a file named "User.cs".
Add the following code into it:
namespace CRUD_NETCore_TDD.Infra.Models
{
public class User
{
public User()
{
}
public User(int Id, string Name, int Age, bool IsActive)
{
this.Id = Id;
this.Name = Name;
this.Age = Age;
this.IsActive = IsActive;
}
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool IsActive { get; set; }
}
}
The "User" model is completed. Inside the "PostUserTest.cs" file, copy and paste the "Fact_PostUser_NoModelNoRepository" method and comment the original. Change the copy's name to
"Fact_PostUser_NoRepository" and import the "User" class. The full code will be like this:
using CRUD_NETCore_TDD.Infra.Models;
using Xunit;
namespace CRUD_NETCore_TDD.Test.Tests
{
public class PostUserTest
{
#region THEORY
#endregion
#region FACT
//[Fact]
//public void Fact_PostUser_NoClassNoRepository ()
//{
// // EXAMPLE
// var user = new User("LUCIANO PEREIRA", 33, true);
// // REPOSITORY
// ctx.User.Add(user);
// ctx.SaveChanges();
// // ASSERT
// Assert.Equal(1, user.Id);
//}
[Fact]
public void Fact_PostUser_NoRepository()
{
// EXAMPLE
var user = new User(0, "LUCIANO PEREIRA", 33, true);
// REPOSITORY
ctx.User.Add(user);
ctx.SaveChanges();
// ASSERT
Assert.Equal(1, user.Id);
}
#endregion
}
}
Now, it is only missing the "ctx" object to make the code compile.
It will be necessary to install 3 packages through Nuget:
- "Microsoft.EntityFrameworkCore" and "Microsoft.EntityFrameworkCore.SqlServer" packages inside the Infra project;
- "Microsoft.EntityFrameworkCore.InMemory" package inside the Test project.
Create a new folder named "Repositories" inside the Infra project containing the "MyContext.cs" file with the following code:
using CRUD_NETCore_TDD.Infra.Models;
using Microsoft.EntityFrameworkCore;
namespace CRUD_NETCore_TDD.Infra.Repositories
{
public class MyContext: DbContext
{
public DbSet<User> User { get; set; }
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>(e =>
{
e
.ToTable("user")
.HasKey(k => k.Id);
e
.Property(p => p.Id)
.ValueGeneratedOnAdd();
});
}
}
}
What we have here is the basics for the EF Core to work in our project. The "user" table does not need to exist yet because will make the database to run in runtime memory.
Inside the Test project, create another file inside the "Tests" folder named "BaseTest.cs". It will be a super class containing the following code:
using CRUD_NETCore_TDD.Infra.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace CRUD_NETCore_TDD.Test.Tests
{
public class BaseTest
{
protected MyContext ctx;
public BaseTest(MyContext ctx = null)
{
this.ctx = ctx ?? GetInMemoryDBContext();
}
protected MyContext GetInMemoryDBContext()
{
var serviceProvider = new ServiceCollection()
.AddEntityFrameworkInMemoryDatabase()
.BuildServiceProvider();
var builder = new DbContextOptionsBuilder<MyContext>();
var options = builder.UseInMemoryDatabase("test").UseInternalServiceProvider(serviceProvider).Options;
MyContext dbContext = new MyContext(options);
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
return dbContext;
}
}
}
The "BaseTest" class is responsive for instantiating the "MyContext" class and make it run in memory without the need of a database previously created. All the write and read operations will work perfectly. If another "MyContext" instance exists, it will be passed as parameter to the constructor.
Make the "PostUserTest" class to implement the "BaseTest" class and the code will be finally be able to compile. Copy and paste the "Fact_PostUser_NoRepository" method, comment the original and rename the copy to "Fact_PostUser". The code will be like this:
using CRUD_NETCore_TDD.Infra.Models;
using Xunit;
namespace CRUD_NETCore_TDD.Test.Tests
{
public class PostUserTest: BaseTest
{
#region THEORY
#endregion
#region FACT
//[Fact]
//public void Fact_PostUser_NoClassNoRepository ()
//{
// // EXAMPLE
// var user = new User("LUCIANO PEREIRA", 33, true);
// // REPOSITORY
// ctx.User.Add(user);
// ctx.SaveChanges();
// // ASSERT
// Assert.Equal(1, user.Id);
//}
//[Fact]
//public void Fact_PostUser_NoRepository()
//{
// // EXAMPLE
// var user = new User(0, "LUCIANO PEREIRA", 33, true);
// // REPOSITORY
// ctx.User.Add(user);
// ctx.SaveChanges();
// // ASSERT
// Assert.Equal(1, user.Id);
//}
[Fact]
public void Fact_PostUser()
{
// EXAMPLE
var user = new User(0, "LUCIANO PEREIRA", 33, true);
// REPOSITORY
ctx.User.Add(user);
ctx.SaveChanges();
// ASSERT
Assert.Equal(1, user.Id);
}
#endregion
}
}
Run the tests with the Test Manager to see the result:
Finally, our Green step is done!
Next
Time to refact the code.
Posted on December 16, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.