DbTest 1.1.4
dotnet add package DbTest --version 1.1.4
NuGet\Install-Package DbTest -Version 1.1.4
<PackageReference Include="DbTest" Version="1.1.4" />
<PackageVersion Include="DbTest" Version="1.1.4" />
<PackageReference Include="DbTest" />
paket add DbTest --version 1.1.4
#r "nuget: DbTest, 1.1.4"
#addin nuget:?package=DbTest&version=1.1.4
#tool nuget:?package=DbTest&version=1.1.4
DbTest
DbTest is a tiny test library for integration test with EntityFrameworkCore in .NET application. It helps you to write tests with a real database very easy and native. It does only dirty work with the database, and you still need NUnit, XUnit or any of your favorite test framework.
DbTest gives you clean database for each test. It offers easy and maintainable way to create initial fixtures and test cases.
Motivation
Common approach to test .NET application that work with database is to separate data access code from business logic code. This Data Access Layer will be substitute by mocks in tests. It is very power and flexible method, but it also has some disadvantages: producing many boilerplate types, complexity growth and so on. You have to separate business logic and data access even you don't want it. And the saddest thing you still need to test Data Access Layer.
There is a simpler approach which widespead in dynamic language world. Instead of create and control database abstraction, it offers use real database and control it's state. Test framework gives you clean database before each tests and you can create test case by filling it. This approach is significantly more convenient and understandable. Tests with real database are simpler and give more confidence.
Influences
DbTest is inspired by the test approach from Ruby on Rails, Django, Yii2 and many other perfect dynamic language frameworks. This approach is a very popular in dynamic languages.
What's you get
Clean real database Real database has many aspects that can not be emulated by Data Access Layer: constraints, triggers, complex SQL queries and so on. DbTest reset database to initial state before each test. SqlServer and Postgresql are supported now.
Strong type fixtures There are some libraries that can create initial state throught txt files. Any changes in project can broke those fixtures, because compiler don't process them. DbTest offer a way to describe fixtures in code. You will get autocomplete, refactoring and type checking when you write and maintain fixtures.
Clean and understandable tests Write your tests as a book, even non technical people can read and participate.
Installation
Install in your *.Tests
project:
Install-Package DbTest
You can see usages in Examples
Fixtures
A real system has many relations between models, we need to fill many tables before create one row in a target table. For example, Products can be related to Manufacturers which related to Country.
Let's start from model which has no relations:
public class CountriesFixture : IModelFixture<Country>
{
public static Country Scotland => new Country
{
Id = 1,
Name = "Scotland",
IsDeleted = false
};
public static Country USA => new Country
{
Id = 2,
Name = "USA",
IsDeleted = false
};
}
First of all we need class that realize IModelFixture<T>
interface. Each model instances are declared as static to give easy access to it from any part of other fixtures or tests. You need set identifiers explicitly and control uniqueness between one class of model.
Now, we are ready to create Manufacturers and Products.
class ManufacturersFixture : IModelFixture<Manufacturer>
{
public static Manufacturer BrownForman => new Manufacturer
{
Id = 1,
Name = "Brown-Forman",
CountryId = CountriesFixture.USA.Id,
IsDeleted = false
};
public static Manufacturer TheEdringtonGroup => new Manufacturer
{
Id = 2,
Name = "The Edrington Group",
CountryId = CountriesFixture.Scotland.Id,
IsDeleted = false
};
}
public class GoodsFixture : IModelFixture<Good>
{
public static Good JackDaniels => new Good
{
Id = 1,
Name = "Jack Daniels, 0.5l",
ManufacturerId = ManufacturersFixture.BrownForman.Id,
IsDeleted = false
};
public static Good FamousGrouseFinest => new Good
{
Id = 2,
Name = "The Famous Grouse Finest, 0.5l",
ManufacturerId = ManufacturersFixture.TheEdringtonGroup.Id,
IsDeleted = false
};
}
Pay attention to external keys in models we do not set it explicitly instead take value from another fixture. You give advise from intellisence when create your fixtures and check from compiler when your system change and fixtures must changed too.
Prepare database for test
DbSet apply migrations and clean database before every test, to prepare call this
new EFTestDatabase<MyContext>(SandBox.GetContext());
.ResetWithFixtures(
new CountriesFixture(),
new ManufacturersFixture(),
new GoodsFixture()
);
SandBox
SandBox
is a conception of test environment. It has connection to test database and methods to clean and load initial fixtures
static class SandBox
{
const string ConnectionString = @"User ID=test;Password=test;Host=localhost;Port=5432;Database=test;Pooling=true;";
public static void InitDatabase()
{
new EFTestDatabase<MyContext>(GetContext())
.ResetWithFixtures(
new CountriesFixture(),
new ManufacturersFixture(),
new GoodsFixture()
);
}
public MyContext GetContext()
{
var optionsBuilder = new DbContextOptionsBuilder<StockDbContext>();
optionsBuilder.UseNpgsql(ConnectionString);
return new StockDbContext(optionsBuilder.Options);
}
}
Model builder
Model builder
is a helper to create test case. It is not included in DbTest
, you have to create it. Each methods of this class must
create and return one entity:
public class ModelBuilder
{
public MoveDocument CreateDocument(string time, Storage source, Storage dest)
{
var document = new MoveDocument
{
Number = "#",
SourceStorageId = source.Id,
DestStorageId = dest.Id,
Time = ParseTime(time),
IsDeleted = false
};
using (var db = SandBox.GetContext())
{
db.MoveDocuments.Add(document);
db.SaveChanges();
}
return document;
}
public MoveDocumentItem AddGood(MoveDocument document, Good good, decimal count)
{
var item = new MoveDocumentItem
{
MoveDocumentId = document.Id,
GoodId = good.Id,
Count = count
};
using (var db = SandBox.GetContext())
{
db.MoveDocumentItems.Add(item);
db.SaveChanges();
}
return item;
}
}
Use in test
[SetUp]
public void SetUp()
{
World.InitDatabase(); // Main part, prepare database for test
}
[Test]
public void CalculateRemainsForMoveDocuments()
{
// prepare test
var builder = new ModelBuilder();
var doc1 = builder.CreateDocument("15.01.2016 10:00:00", Storages.MainStorage, Storages.RemoteStorage);
builder.AddGood(doc1, Goods.JackDaniels, 10);
builder.AddGood(doc1, Goods.FamousGrouseFinest, 15);
var doc2 = builder.CreateDocument("16.01.2016 20:00:00", Storages.RemoteStorage, Storages.MainStorage);
builder.AddGood(doc2, Goods.FamousGrouseFinest, 7);
// test
var remains = RemainsService.GetRemainFor(Storages.RemoteStorage, new DateTime(2016, 02, 01));
// assert
Assert.AreEqual(2, remains.Count);
Assert.AreEqual(10, remains.Single(x => x.GoodId == Goods.JackDaniels.Id).Count);
Assert.AreEqual(8, remains.Single(x => x.GoodId == Goods.FamousGrouseFinest.Id).Count);
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net8.0
- Microsoft.EntityFrameworkCore (>= 8.0.10)
- Microsoft.EntityFrameworkCore.Relational (>= 8.0.10)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 8.0.8)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on DbTest:
Package | Downloads |
---|---|
DbTest.EFCore
Extension for DbTest to use with Entity Framework Core |
|
DbTest.EF6
Extension for DbTest to use with Entity Framework 6 |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.1.4 | 122 | 10/16/2024 |
1.1.3 | 98 | 10/15/2024 |
1.1.2 | 93 | 10/15/2024 |
1.1.1 | 100 | 10/15/2024 |
1.1.0 | 90 | 10/15/2024 |
1.0.0 | 109 | 10/15/2024 |
0.2.0 | 1,708 | 3/8/2018 |
0.1.8 | 1,280 | 5/22/2017 |
0.1.7 | 1,079 | 5/22/2017 |
0.1.6 | 1,078 | 5/22/2017 |
0.1.5 | 1,128 | 1/10/2017 |
0.1.4 | 1,306 | 1/10/2017 |
0.1.3 | 1,190 | 1/2/2017 |
0.1.2 | 1,170 | 1/2/2017 |
0.1.1 | 1,189 | 1/2/2017 |
0.1.0 | 1,185 | 1/2/2017 |