views:

1009

answers:

6

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.

A: 

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
someone recommend to do transaction and rollback with test db, what do you think of this approach of testing DAL?
ray247
Transaction and Rollback, in my experience, has been slow.
y0mbo
you can simulate exceptions caused by failed transactions with mocking.
tvanfosson
+6  A: 

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
+3  A: 

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.
+1  A: 

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
A: 

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
A: 

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