Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Entity Framework with fixtures

One of the things I like about Rails' and Django's testing approach is their support of using fixtures to set up a database before each test is run.

In the past, I've used strict unit tests in conjunction with a mocked repository to test my code, but I'd love to have something that's as easy to use as the aforementioned testing approaches in order to do integrated testing.

I've heard some talk of this type of support with code-first and EF 5, but I don't know if it rises to the level of what Rails and Django provide.

Surely there's something comparable out there. Any information would be appreciated!

like image 940
Bret Walker Avatar asked Jul 03 '12 23:07

Bret Walker


People also ask

Should I use in-memory database for testing?

This database provider allows Entity Framework Core to be used with an in-memory database. While some users use the in-memory database for testing, this is generally discouraged; the SQLite provider in in-memory mode is a more appropriate test replacement for relational databases.

What is a test fixture xUnit?

In xUnit, a test fixture is all the things we need to have in place in order to run a test and expect a particular outcome. Some people call this the test context.


2 Answers

In EF5 new concept has been introduced, called Migrations. You probably used to use something similar in Rails or Django applications.

Migration is a class, that has several functions to upgrade / downgrade the version of DB.

public partial class VoteTime : DbMigration {     public override void Up()     {         AddColumn("Votes", "Time", c => c.DateTime(nullable:false, defaultValue:DateTime.UtcNow));     }      public override void Down()     {         DropColumn("Votes", "Time");     } } 

You also, have to setup DbContext and DbMigrationsConfiguration configuration classes to allow code first approach to work.

For testing purposes you need to introduce, TestDatabaseInitilizer

public class TestDatabaseInitilizer : DropCreateDatabaseAlways<DbContext> {  } 

It would be responsible for initialization of test database for unit tests.

Finally, you should design your test code to setup the context.

public class SomeRepositoryTests {     private DbContext _context;      [SetUp]     public void Setup()     {         Database.SetInitializer(new TestDatabaseInitilizer());         _context = new DbContext("TestContext");         _repository = new SomeRepository(_context);     }      [Test]     public void should_return_some_entities()     {         Assert.That(_repository.Get(), Is.Not.Null);     } } 

The setup code could be moved to base class, if required.

like image 52
Alexander Beletsky Avatar answered Oct 20 '22 16:10

Alexander Beletsky


I've developed an application with Entity Framework that has over 600 automated integration tests. This is the process I used:

  • Entity Framework code first migrations just to set the database structure (tables, indexes, etc.). I don't use migrations to seed data.

  • SQL scripts that set the database in specific, well-known states. For instance, one script to insert ASP.NET membership users; another that sets sample data for the most relevant tables; and others for more specific scenarios. The scripts typically delete the records from the appropriate tables and insert them again, in the appropriate order to avoid relationship conflicts. The scripts are included in the Visual Studio project as embedded resources.

  • A helper class that can get a script from the resources by its name and execute it against the database, including batching commands with "GO". ConnectionContext.ExecuteNonQuery can be used for that.

  • At the start of the whole test suite, I execute the script that sets up users, permissions and other very general environment configurations.

  • Before each test method, I execute one or more scripts, as appropriate, to set the database in the context required by the tests being run. For instance, before a series of CRUD tests that read, insert, update and delete data, I run a script that seeds the appropriate table with test data.

  • I write the test cases assuming the database is set in a specific context. For instance, a test of an update operation will try to retrieve a record with a known key, update it and read again to check if it was updated in the database.

Although SQL scripts are not as easy to write and read as Rails fixtures, they're very fast and can do any kind of manipulation needed (e.g. DELETE, INSERT, UPDATE, execute stored procedures).

This technique was well proven in a project involving 50 database tables and very complex business rules and processes. It kept the tests simple and consistent.

like image 44
Fernando Correia Avatar answered Oct 20 '22 15:10

Fernando Correia