Skip to end of metadata
Go to start of metadata

The Spring fallacy

Spring proponents will have you believe that "Unit Testing" of persistent classes is very hard without spring. This is not the case, and can be accomplished in only a few classes.

This is not spring-bashing - I'm sure that Spring is very useful for some. This is simply an alternative approach to one that was presented at InfoQ

Requirements

To use these examples you will need the following libraries - all open source

Persistance

We will be using a simple annotated class just to show the example.

Loan.java

The Persistent Stuff

This is where you might have used the ejbFindBy methods back in the day... its just an interface.. so you can conveniently have mocks and stubs for them.

Loans.java

And an implementation for the interface

Using an EntityManager. This means that we will create them in the transactional context in which they are used, rather than having them around for ever - as we might have used with an EntityManagerFactory. Short lived objects are very efficent these days.

PersistentLoans.java

Transactional Context

If we are to have any hope of using the entity manager outside of a J2EE container, then we need to do so within a transaction. Managing this as part of a testcase is a bit hit-and-miss - better abstract it.

Transactor.java
UnitOfWork.java

Creating a test Configuration

All systems have some way of getting their configuration. In real code the implementation here would be a little more intelligent.

SystemConfiguration.java

Creating a test Entity Manager

This example uses Hibernate and Oracle, but you could do this with lots of other implementations. Note that the actual implementation doesn't escape - as far as the rest of the code is concerned, we are still only talking about EntityManagers.

To keep the amount of code in this page short - I used the autoDDL feature of hibernate. I would suggest never do this, and make sure to have a good database rebuilding script as part of the build process. Dropping and recreating databases takes only seconds.

TestConfiguration.java

Builders

We like to use the Builder pattern - it makes code much cleaner!

The actual persistence test

PersistentLoansTest.java

How it all looks

Here's a screenshot from IntelliJ after we have put all the code together.

Contact me - using the contact me page if you would like access to the svn repo. All the code is here though.

Screenshot

Thanks

Nat & Nick

Complaints

To me...

Labels:
  1. Nov 21, 2007

    Anonymous

    This is helpful, thanks for the post. Perhaps your own article on InfoQ next time?

    JAW
    http://jawspeak.com

  2. Feb 05, 2008

    Anonymous

    The matcher should be hasSameTransientFieldsAs, not hasSameNonTransientFieldsAs,

  3. Aug 12, 2009

    Anonymous

    well, too much code to achieve the same thing compared using spring.

    1. Feb 17, 2010

      Anonymous

      Much code ? Even considering spring-xxx.jar ?
      EricMinio

    2. Feb 08, 2012

      Anonymous

      I would buy from the frneid. Whether I bought from the frneid or the authority I would check out the product to determine, to be best of my ability, if the product was what it was being presented to be.
  4. Feb 17, 2010

    Anonymous

    I like the way you've managed to simplfy JUnit testing and my team and l, are going to go with your approach.You've greatly simplified the approach that Spring uses, and you've taken away the dependency of Unit testing using Spring, you approach seems seemless and easier to use.

    1. Feb 18, 2010

      Thanks - The approach is documented in greater detail in Growing Object Oriented Software Guided By Tests

      I find that by just using plain old java with sensible constructors and no pointless frameworks code stays clean and totally refactorable.

      You can contact me using the Contact Us page if you wanted more information etc (saves my posting my email address for scammers here!)

  5. Sep 11, 2010

    Anonymous

    James,

    I actually like your approach quite a bit, though I notice your domain object (Loan) does not contain any behavior. It's merely getters and setters.

    If you needed to inject some sort of behavior into the object (Composites, Strategy objects etc), how would you accomplish that? Through constructor injection?

    Or are you more of a fat service advocate?

    Thanks for the great post.

    • matt

    I realize this post was a while ago, but I thought I'd ask in case you are monitoring.

    1. Sep 13, 2010

      Good question.

      The Loan object doesn't do anything here. The point of the article was about handling the persistent fields, and checking that they round trip into the database.

      If you did need it to do something, then you can of course just write some methods!

      I'm not quite sure what you mean about "injecting behaviour" though. If an object needs a collaborator to do something then you can just give it to the object when you ask it to do that thing.

      e.g.

      Some methods may not need an obvious external service, but may instead just execute in a transactional context.

      e.g.

      1. Feb 08, 2012

        Anonymous

      2. Feb 09, 2012

        Anonymous

        L1Tk7G , [url=http://znpxscamqfxc.com/]znpxscamqfxc[/url], [link=http://lvdqqrxhypym.com/]lvdqqrxhypym[/link], http://tzcgisupimtf.com/
      3. Feb 09, 2012

        Anonymous

        IvxpXL , [url=http://pfabqbgcnghe.com/]pfabqbgcnghe[/url], [link=http://mwvyfgswucrq.com/]mwvyfgswucrq[/link], http://fclugxyssvxg.com/