5

I'm currently developing a Spring-based web-application, in which almost every operation create/update/delete something in the database. The logic mostly about checking condition so as to we should create/update records in the database or not.

The reason I want to try unit test is that we often meets regression errors when request changes or refactor. Most the bugs comes from Database changes, when I doesn't fully reflect those changes in the code. I have some experience in web-development now, but it seems that's not enough to stop them appear.

My controller/service is actually not too complex. I just take the binding object submited from the HttpRequest, check the condition & record in DB. Sometimes the system must read the Database, take out some records & manipulate them, then update some other records.Much of the coding effort lies on the interface(HTML/CSS/Javascript) too.

I'm investigating unit test, and I heard that when it comes to database operation, it's no longer unit test, since the test will be slow. Is that true? So that if my project is heavily database-operation, I shouldn't use unit test?

I also heard about DBUnit & some in-memory database which can quicken the test. Should I use them? And how I can write good unit test for database operation?

Hoàng Long
  • 856
  • 1
  • 12
  • 19
  • "when it comes to database operation, it's no longer unit test," Can you find the quote or reference or link and provide that? It's a fallacy, and it's important to see where you got this misinformation from. – S.Lott Jan 12 '12 at 11:02
  • 1
    @S.Lott: here is the reference http://www.artima.com/weblogs/viewpost.jsp?thread=126923 What is meant here is "unit test feasible for Test Driven Development" - those kind of tests should not use a database. – Doc Brown Jan 12 '12 at 12:43
  • @S.Lott: I don't recall it correctly, but a search about Unit test with database call out many results. Here is an example: http://stackoverflow.com/questions/30710/how-to-unit-test-an-object-with-database-queries – Hoàng Long Jan 13 '12 at 05:03
  • It becomes an integration test when there is a dependency on the database or some other component. – Theomax Sep 30 '12 at 11:10

2 Answers2

5

You probably should have unit tests and integration tests. In the unit tests, you test for example your controllers/services in isolation. To achieve that, you may use for example a mocking framework such as Easymock or Mockito to cut the dependency to the database.

Your integration tests should go the whole way, from your controllers/services right to the database. You can write your integration tests with the same basic framework as your integration tests (JUnit or TestNG to name the most popular). I personally like DBUnit to prepopulate a database and verify the database state after the test. Whether you use an in-memory database IMO strongly depends on your persistence layer. If you use for example a JPA framework that generates its own queries, I like having an in-memory db. If you write your own SQL-Queries, it can be more difficult to use another DB than your production target as you cannot be sure that the syntax is gonna be equivalent, so an integration test against e.g. an in-memory H2 database not necessarily means that the Syntax works with DB2. This becomes even more problematic if you use stored procedures.

A good integration test itself runs in isolation, meaning that you should set up the database before each test to avoid dependency among tests. You don't want the success of your tests depend on the order they are executed in. After you perform your operations, you should use some kind of assertions to test if the database state is conforming to your expectations. DBUnit for example has its own asserts for comparing Datasets or Tables.

ftr
  • 1,601
  • 1
  • 14
  • 19
  • 1
    I'll add that the distinction between whether its a Unit test or an Integration test doesn't really matter. What matters is that you're testing vital pathways in your code :-) – Martijn Verburg Jan 12 '12 at 09:00
  • @ftr: This field is pretty new to me. If I use Hibernate Criteria, is it guaranteed that what happens in the test environment is the same as the production? – Hoàng Long Jan 13 '12 at 06:55
  • 1
    @Hoàng Long I have never used Hibernate Criteria so far, but from what I've read, it isn't on a plain SQL level but translates into dynamic queries, so it *should* be portable across Hibernate-supported databases. I cannot guarantee that, though. – ftr Jan 13 '12 at 07:48
1

I also heard about DBUnit & some in-memory database which can quicken the test. Should I use them?

Yes.

And how I can write good unit test for database operation?

Same way you write any other unit test.

You look at the defined interface for your class (or method) and write a test that demonstrates that it works when it's supposed to work and breaks when it's supposed to break.

Your setup may be somewhat complex because you have to put rows into the database that match the requirements of your unit test.

S.Lott
  • 45,264
  • 6
  • 90
  • 154
  • thanks, I means to ask if there's any difference in using an in-memory database. About the practice, do you know any good example for this kind of unit test? I know the theory, but in reality, I found that my test seems to be a little silly (it's too obvious). – Hoàng Long Jan 13 '12 at 07:31
  • It will be silly and obvious. That's okay. In more complex applications, it may be less silly. – S.Lott Jan 13 '12 at 12:06