2

We're using MVC, Entity Framework 4.1 Code First, SQL Server in our project.

Please share your experience: how do you unit test your data service layer? By data service layer I mean services supposed to be run by MVC controllers that have some kind of DbContext derived class declaration inside, so that they depend on this EF DbContext, and encapsulate some business\data logic to fetch and store the data.

After reading few articles and posts, I incline to use separate database to build unit/integration tests on, and I prefer to use in-memory (like SQLite) rather than SQL Compact. However I'm not even sure if it's possible, if you have such an experience, could be please share few lines of code to show how you achieve this.

YMC
  • 4,925
  • 7
  • 53
  • 83

2 Answers2

5

Unit testing means testing unit = no database, no external dependency, just testing single testable unit. Once you want to involve database you don't unit test any more - you are doing integration testing.

I wrote multiple answers about unit testing / integration testing of code dependent on EF. The last one is here. So if your service layer creates linq queries on context you cannot reliably unit test them. You need integration tests.

I would use the same database as you expect to use in your real code. Why? Because mapping and behaviour between database provides can differ as well as implementation of LINQ. Also in case of SQL server you can use special EF features which don't have to be available in SQLite. Another reason is that last time I checked it, SQLite's provider didn't support database deletion, recreation, etc. which is something people usually want to use for integration tests. Solution for that can be Devart provider.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Right, I'm talking about integration tests. I mentioned unit tests just to let you know this integration tests supposed to replace unit tests for the service level to some extent, I mean I'm not going to do both thins. Thanks for info regarding SQL Lite. – YMC Aug 04 '11 at 22:38
  • I'd like to add to my previous comment: My concern regarding file system based (not in-memory) database is performance. Unit test are part of our build process and bunch of database operations may harm build's overall performance – YMC Aug 04 '11 at 22:46
  • @YMC: You will always need integration tests if you want to test application using the database. The only question is how many of them would you need. Do you want to test your application? So pay the price and live with slower builds or setup build server and let builds and integration tests execute on separate machine. – Ladislav Mrnka Aug 05 '11 at 07:54
  • I just assume using SQLite and its in-memory provider would improve unit tests performance few times, and in the same time they are true integration tests meaning they gonna test LINQ->SQL mapping too. I know its separate provider with its own SQL script generation engine that may differ from SQL Server provider in production, but I hope it can help us to catch most of potential mapping issues. – YMC Aug 05 '11 at 21:44
1

I don't use a separate database at all. In fact, my Unit Tests don't use a database at all.

My strategy is to create IEnityRepository interfaces for the DB Entities (replace Entity with the actual name). I then pass those to the constructor for my controllers.

During Unit Testing, I simply use a Mocking library to pass mock implementations of the repositories that I need and have the return some set of known data that I can use in the Unit Tests.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • I thought about it too. However I prefer integration tests because of 2 reasons: 1) it's more likely you find LINQ expression -> SQL script mapping problems using real database, not mocks 2) You do have to add additional layer to hide DbContext from data service you want to apply unit tests for – YMC Aug 04 '11 at 22:32