32

Earlier I asked this question How to correctly unit test my DAL?, one thing left unanswered for me is if to really test my DAL is to have a Test DB, then what is the role of mocking vs. a testing DB?

To add on this, another person suggested to "use transactions and rollback at the end of the unit test, so the db is clean", test db that is. What do you guys think of this testing + test DB + transaction rollback (so db is not really written) approach to test DAL?

To be complete, my DAL is built with Entity Framework, there is no stored proc in DB. Since EF is so new, I really need to test DAL to make sure they work correctly.

Community
  • 1
  • 1
Ray
  • 12,101
  • 27
  • 95
  • 137

8 Answers8

18

I think you'll probably want to do some integration testing to check logic that is enforced by your database structure, for example constraints, triggers, autoincrement columns, etc. You should, however, for unit testing mock out whatever framework components that your DAL relies upon as you want (in your unit tests) to test only those components that you have coded. You don't really need to test methods on SqlCommand or SqlConnection (for example). You should assume that the framework components that you use work and create stubs or mocks for them that return known data (good, bad, exceptions) to your methods to make sure that your methods work properly. Without mocking you are responsible for generating the data in the database and making sure that it is correct. You also leave open dependencies on the network, the database itself, etc. that may make your tests brittle.

Also, unit testing does not remove the need for other types of testing. Integration tests and acceptance tests are still valid and need to be done. They probably don't need to be done with the same frequency as unit tests and may not need to be as extensive as your code quality improves with unit testing, but unit testing is not a magic bullet.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 2
    +1 integration testing still have it place. @ray247 Keep in mind than mocking is just to test lower layers such business layer because in thoses test your just interested to know if your business layer work.. not the DB so your mock will "act like a database that return something". – Rushino Dec 14 '11 at 14:17
13

I didn't find mocking very useful when testing data access code. The purpose of unit testing is to verify the database-related code works and mocking the database would hinder the test.

Mocking does indeed become useful when testing the business code. You can mock your database calls to return test data and verify the behavior of business logic in those circumstances.

Regarding the use of transactions - it's certainly possible, as long as your architecture has room for starting a transaction at the beginning of the test, and then doing all database-related calls of your unit test inside that transaction. Never tried it, though.

Dan C.
  • 3,643
  • 2
  • 21
  • 19
5

Putting unit tests into transactions that roll back sounds hacky. Instead of that I have code that cleans the database of any crud (i.e. anything that isn't static/reference data) before the tests run (i.e. in the constructor of my test class). When your tests fail it helps to have the data still in the database to inspect what the cause of the failure is.

Craig Fisher
  • 1,681
  • 2
  • 19
  • 26
1

Your not just testing your app, though. You are also testing your configuration and your Stored Procedures and Views. These are documented in your unit tests.

user447607
  • 5,149
  • 13
  • 33
  • 55
1

we've used transactional unit tests and that prevented Hibernate mapping problems several times. Otherwise - what's to unit test? Something trivial as List<Item> getAllItems()? :)

miceuz
  • 3,327
  • 5
  • 29
  • 33
0

By using a test database, you open up the possibility that problems could be caused at the database itself or along the communication path (network, etc) between the DAL and database. Mocking eliminates those possibilities.

ahockley
  • 3,696
  • 24
  • 26
0

It's not only the state of the DB you must consider, it's also availability. If your DB is offline why should all of your DAL tests fail?

What you need to test is that your DAL issues the correct commands in order to create / retrieve / update / delete. You don't need to execute SQL for this, you can just use an object persistence framework and check that you give it the correct instructions.

Peter Morris
  • 20,174
  • 9
  • 81
  • 146
-1

The problem could very well be in the original question. Some of the more popular examples of MVC use a shortcut by returning a DbSet such as:

public class MusicStoreEntities : DbContext
    {
        public DbSet<Album> Albums { get; set; }
        public DbSet<Genre> Genres { get; set; }
        public DbSet<Artist> Artists { get; set; }
        public DbSet<Cart> Carts { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
    }

To me this tightly couples the implementation of persistence which I believe is a bad thing. It woud be better to return List<t> which could easily be mocked.

biegleux
  • 13,179
  • 11
  • 45
  • 52