Ok, raise your hand RIGHT NOW if you said “Oh my” after “Dependency Injection, Interfaces, and Mocking”. If you didn’t, drop what you’re doing and go rent “The Wizard of Oz” because you’re really missing a monumentally important American cultural reference.
I don’t recommend the adoption of new shop standards very often for my team. Yes, I like us to be nimble and up to speed as much as possible, but I’m not really a bleeding edge kind of guy. I like standards that solve REAL problems.
Real Problem #1:
How do you write a unit test for a unit that depends on other units that you don’t have yet?
Real Problem #2:
How do you send your application to a super smart friend (who will be able to fix your 2 month old bug in 2 seconds) when the application depends on internal resources such as a database?
Real Problem #3:
What if you’re coding the Service tier, and some other guy is developing the persistence tier and he keeps changing his implementation in a way that causes you to have to change your implementation?
“Ok, David, here’s the new class and here’s how you instantiate it.”
“Great, thanks, Joe. I just finished building, testing, and deploying my application. I’d just LOVE to do it again.”
Ok, so these are real problems that my real team of RAJPs have struggled with over the last year. If you are not a RAJP (say, a JG (Java Guru) or a JPE (Java Programmer Extraordinaire)) you probably have a super duper array of frameworks and techniques to solve this problem that I will not figure out how to use until my RAJP solution is no longer working for me.
Step 1: Write all of your DAO classes to an Interface.
Writing to an Interface is the design foundation for all things loosely-coupled.
Step 2: Implement a Mock and a fully Implemented version of all your DAO classes (to an Interface of course). If you have any other DAO alternatives (a web service, a local cache for offline use, or whatever) be sure to implement the same interface.
You probably want to start with the Mock implementation first. This will get you up and going quicker.
Notice the use of test data in my mock.
When you finally get around to fleshing out your DAO then you’ll start with something more like this.
Step 3: Inject DAO instances into your Service object based on specific deployment needs.
There are a lot of different ways to accomplish Dependency Injection. We’re using Spring.
I specify which implementation of PickleDAO to use at runtime in a Spring Configuration file. For this deployment, I’m instantiating PickleDAOMock
All that remains is a simple injection…I promise it won’t hurt!
Now, I can just hear some of the guys on my team whining about how many more source files are required to accomplish this design. Here’s what it looks like:
But come on, guys! This is how we make our living…writing code!
If you design your persistence layer with this pattern, you will provide optimum flexibility with loose coupling. This solves all three of the problems that I described above.
Problem #1: When testing units that depend on a DAO that you haven’t fleshed out yet, switch the configuration to inject the Mock DAO.
NOTE: The Spring folks recommend directly instantiating your Mock objects in your unit test rather than injecting. I’m not yet experienced enough with unit testing to argue for or against this, so I’ll just leave at that.
Problem #2: Before you send your code off to your super smart friend, reconfigure your Spring config to instantiate a Mock or some other kind of instance that won’t require that resource.
Problem #3: The persistence guy can switch DAO implementations to his heart’s content without the Service guy ever noticing. Worst case scenario is that the Service guy has to change his Spring config.
Perhaps one day, I’ll get tired of writing my own mocking and will use JMock or something slick like that. If I do, I’ll be sure to tell you about it. Until then, I’ll stick with my Regular Average Java Programmer approach.