tags:

views:

59

answers:

3

Hi All,

i would like to ask you about writting tests which are connected with data from database. In my opinion the best way is to have a diffrent DB schema with correct data only for unit testing. In test code i can load the object on the base of ID.

The second possiblity is to putting data into database during the unit test. I dont like it.

What do you think. How do you do this?

Kind regards Sebastian

A: 

For unit tests, you should mock or stub the functionality of the database. Since you are testing the object that calls the database and not the database itself, there is no need to use a real database. EasyMock or JMock are good mocking libraries to look into.

Jeff Storey
Thanks. What if i have a big object graph? Then i need to write much code to mock every reference to other object.Im using mocking in Service layer to mock the DAO layer because the DAO layer was arleady tested. And im also use mocking in GUI layer to mock the Service layer because the Service layer was already tested.Dont you think that mocking database to test the DAO layer is not so good idea? We want to test it, but in this case we will be testing mock objects. What do you think? Thanks for answer.
Sebastian
If there are too many objects to mock, it could mean your design is too complicated and one class maybe has too much responsibility. Without seeing the actual code, it's tough to tell but see if you can simplify it a bit.As for the database, if you're mocking the database, you're not testing a mock object if your test is for the DAO. You're testing that the DAO sends the correct commands to the database. For a DAO test, it is safe to assume the database will behave as expected (and you can always mock it to do unexpected things to test error cases).
Jeff Storey
Thank you very much.
Sebastian
A: 

Three comments:

  1. Unit tests are typically small scale, fast tests to cover a little piece of code. Tests using a DB are not really unit tests (even if you can run them in e.g. JUnit), but rather system / integration tests. Both are useful, for different purposes.

  2. Even if your object graph is big, I don't see why you would need to test it all at once in a unit test. You test one DAO with the necessary mock objects, and assert that the relevant part of the object graph is handled correctly. Then write more tests for the next DAO etc.

  3. IMO DAOs typically should not do very complex things (unless part of the business logic is put in there, but that's bad design - should be refactored instead of trying to cover it with contorted unit tests).

Péter Török
Thank you very much.
Sebastian
A: 

If you really want to write tests that interact with a database - integration tests - then you will have to put your database in a known state before each test execution.

One way to do this would be to load custom dataset before each test, for example using DbUnit. Here, each test is responsible of his own data, there is no cleanup required and you can query the database after a failed test to understand the problem.

Another way would be to use a "live" database and to run tests inside a transaction and to rollback the changes at the end of the test. Spring and Unitils have support for this. This works well too but it's not always easy to diagnose a failed test when using this approach.

Note that the second approach doesn't really exclude the first one, you can use custom dataset inside a transaction. Also note that you can use a database containing "reference data" (i.e. read-only data like countries, etc) and only load "dynamic data" to speed up things when using the first approach.

Personally, I don't really see what's wrong with the former approach (except maybe that tests are a bit slower), tools like DbUnit make it quite easy. And as I said, I find tests using DbUnit easier to diagnose. But the later approach definitely works too.

In both case you should of course use a dedicated schema1.

1 Actually, using one schema per developer is definitely a best practice.

Pascal Thivent
Great!!! Thank you very much.
Sebastian
Pascal, nice detailed answer. You mentioned it in there but I think it's important to stress that tests that interact with a live database are generally integration tests. Using a live a database for a unit test would be overkill and mocking it would be appropriate.
Jeff Storey