• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Non J2EE transactional management in Java

 
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Jdbc Gurus,

I have a dao class that does crud operations on a postgressql database. Some of the queries are plain prepared statements while others are callable statements. The tables that I am accessing are related to one another by standard foreign key/unique key constraints.

I want to write unit tests for my dao classes. If I need to test my method that inserts into a database, I would have to do a clean delete after the insert is done and assertions are complete. This is tricky and can go wrong given the relationship between the table and because some of the logic is executed by stored procedures. If the queries fail, then I will be left with stale and incorrect data.

What I would like to do is the following:

My unit tests would be transactional. Within the boundaries of the transaction, I could call the dao crud methods, validate my assertions and roll back the changes to a prior known state without fail after my tests have been executed. It does not matter if my tests have succeeded or failed.

I know that servlet containers provide an implementation of JTA that could be used for transactional management, but since the unit tests are to be executed outside of the servlet container, I would like to use an implementation (open source) that could be used for transactional management. I know Spring framework has transaction management for unit tests, but we don't use Spring in our application and it is not feasible for create an Application Context for merely testing purposes.

Are there any open source JTA implementations or any other transactional management tools that are available that any one knows of that could be used outside of any servlet containers for purposes of unit testing? Any assistance would be appreciated.
 
Bartender
Posts: 2661
19
Netbeans IDE C++ Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm, never thought about this option for testing. Might work if your test database can manage big transactions.

We usually avoid actually accessing a database while unit testing (see loads of evidence on the ranch and web).
Have you thought about using mock objects? You will probably get good answers on database/dao related testing in the Test forum.
 
author
Posts: 4335
39
jQuery Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've been in this situation before, and what you need to know first off is that any unit test that involves a database, is not a unit test. Unit tests, the true meaning of them anyway, is a test that's completely, 100%, isolated from outside interactions.

In short, you can write JUnit test cases (not all JUnit tests are unit tests, nor do they need to be) that access a database but they are painful to write, at best, because you need to setup test data. Often times, I've used a JUnit's setUp/tearDown methods to setup database data, but its not for the faint of heart since the ability to screw things up is high, especially if your test case fail. At the very least, such a thing should never be run on a production database.

I'm guessing you have a business requirement (boss perhaps?) that is asking for unit tests of database-related code (often is the case). You have 4 choices:
  • 1. Try to get out of it by explaining that database/transactional test cases are not unit tests, but integration/system testing.
  • 2. Write JUnit tests that setup test data in the database before/after the test has been run
  • 3. Use a tool to fake a database specifically made for testing. Believe it or not such tools do exist, although they can be cumbersome to use. I once used this product for testing and simulating a database: Agitator
  • 4. Rewrite your classes so that all the 'important' business logic is in non-database related functions that can be tested as a unit. Systems that use object-relational mapping tools adapt naturally to this pattern.
  •  
    kartik krishnan
    Ranch Hand
    Posts: 63
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    @Jan - We use mock objects for testing a class in isolation. That is fine with us.

    In our application, quite a bit of business logic is database driven. We need to test to test CRUD operations.

    @Scott My answers are given below:




    Post Today 10:36:05 AM Subject: Non J2EE transactional management in Java
    I've been in this situation before, and what you need to know first off is that any unit test that involves a database, is not a unit test. Unit tests, the true meaning of them anyway, is a test that's completely, 100%, isolated from outside interactions.

    In short, you can write JUnit test cases (not all JUnit tests are unit tests, nor do they need to be) that access a database but they are painful to write, at best, because you need to setup test data. Often times, I've used a JUnit's setUp/tearDown methods to setup database data, but its not for the faint of heart since the ability to screw things up is high, especially if your test case fail. At the very least, such a thing should never be run on a production database.

    I'm guessing you have a business requirement (boss perhaps?) that is asking for unit tests of database-related code (often is the case). You have 4 choices:
    # 1. Try to get out of it by explaining that database/transactional test cases are not unit tests, but integration/system testing.


    We need to write integration tests so we need to write tests to test end to end flow. I have mocked connection and callable statement interfaces for unit testing the dao layer. But I still need to verify that stored procedure query or prepared statement signature has been implemented correctly in my Java code.

    # 2. Write JUnit tests that setup test data in the database before/after the test has been run


    This is root of the problem. I am not sure how to do this. Ideally the data in the database would be restored to a known state after the test execution and the states before and after the execution would exactly match. So after an insert query (say), I need to be able to rollback to a previous known state.

    # 3. Use a tool to fake a database specifically made for testing. Believe it or not such tools do exist, although they can be cumbersome to use. I once used this product for testing and simulating a database: Agitator


    My boss is not interested

    # 4. Rewrite your classes so that all the 'important' business logic is in non-database related functions that can be tested as a unit. Systems that use object-relational mapping tools adapt naturally to this pattern.


    For our project, this is impossible, as this application is legacy app and we have been implementing business logic in db for the past
     
    Scott Selikoff
    author
    Posts: 4335
    39
    jQuery Eclipse IDE Java
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    kartik krishnan wrote:This is root of the problem. I am not sure how to do this. Ideally the data in the database would be restored to a known state after the test execution and the states before and after the execution would exactly match. So after an insert query (say), I need to be able to rollback to a previous known state.



    As I said, its not for the faint of heart. If your boss truly wants the states to be identical, then you could setup a backup/restore database utility by hand and/or accomplish the same via JDBC. In short, the code to test to your logic may be more complicated than the code your testing. There's no simple answer, if your boss wants it this way then your stuck recreating the database on every test.

    The only advice I can offer is try to go into the office with the philosophy "Well if I have time to write test code, I probably have time to work on something else". After all, its been my experience 99 out of a 100 something comes up before you can finish test code.

    As a side note... the real problem with this type of test is that databases are complex, transactional environments in which you have very little control over whats going on. For example, how do you test concurrency when a database may not execute items in the order you want? Also, if you're not recreating the entire database (say adding/deleting rows of a table instead), you have no control over what the database may be doing with the table or if someone else is accessing it. In short, databases are not single-threaded and unit tests on anything that is not single-threaded and you don't control is non-trivial at best, mind-numbing at worst.
     
    With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
    reply
      Bookmark Topic Watch Topic
    • New Topic