gamelan
Search EarthWeb
CodeGuru | Gamelan | Jars | Wireless | Discussions
Navigate developer.com
Architecture & Design  
Database  
Java
Languages & Tools
Microsoft & .NET
Open Source  
Project Management  
Security  
Techniques  
Voice  
Web Services  
Wireless/Mobile
XML  
New
 
Technology Jobs  

   Developer.com Webcasts:
  The Impact of Coding Standards and Code Reviews

  Project Management for the Developer

  Defining Your Own Software Development Methodology

  more Webcasts...




Return in early January to see which technologies and products won.




Developer Jobs

Be a Commerce Partner














 


Developer News -
Shifts for Enterprise Linux, Green Networks in '09    December 26, 2008
Gifts for All in Linux 2.6.28    December 24, 2008
Merb Merges With Rails    December 24, 2008
Sun's Unwired Motherboard Plans    December 24, 2008
Free Tech Newsletter -

Guicing Up Your Testing
By Dick Wall

Go to page: Prev  1  2  3  4  5  Next  

Getting Guiced

This is where Guice is a perfect fit. It allows you to define a configuration up front that maps implementations of objects to some method of looking them up. When you ask Guice for an object, it will not only look up the one you intend to use within your current context, but will also go through the object looking for dependencies it needs, and injecting the right instances of those objects for your current context as well. It will do this all the way through the chain, basically auto-wiring your objects into a running system without your having to pass parameters all through the application by hand.

Getting and using Guice is easy. Just go to http://code.google.com/p/google-guice/ and download the guice-1.0.zip file from there (or whatever the latest version is when you read this article). Unpacking the zip file will give you a bunch of jar files. The one you need for now is guice-1.0.jar.

You will need to add this one jar file as a library to your project. The IDE doesn't matter, and I will assume you know how to add a library. Incidentally, the sources provided with this article use the latest milestone build of NetBeans 6.0 (which has come on in leaps and bounds recently), but you should be able to adapt the sources provided to work in any IDE you care to (you will also need JUnit to run the unit tests).

Once the library is added to your project, using Guice is really easy. It is really just a collection of annotations for classes and a simple API for configuring the modules to wire up objects correctly. There is a bit more to it, of course (particularly when you start exploring some of the other Jars in the zip file), but ignore all that for now and just concentrate on the core features.

Getting Back to the Example

So, you know what your example looks like on the database, and you know how you can manually test around that, but what does the example look like on Guice?

You can get the full source code for this Guiced up example by downloading the project zip file.

First up, you want to let Guice know that it has some work to do on the Invoice class. In particular, you want Guice to provide the TaxRateManager to your Invoice for us when you create a new one.

Guice actually can perform three different kinds of injection: constructor, field, and method. There are situations where each of the three are useful, but for this example you will use the constructor injection.

import com.google.inject.Inject;

   private Customer customer;
   private List<Item> lineItems;
   private final TaxRateManager taxRateManager;

   /** Creates a new instance of Invoice */
   @Inject
   public Invoice(TaxRateManager taxRateManager) {
      this.taxRateManager = taxRateManager;
      // set up the line item list
      this.lineItems = new ArrayList<Item>();
   }

   public void setCustomer(Customer customer) {
      this.customer = customer;
   }

The changes here include importing the Inject annotation from com.google.inject.Inject, and the new @Inject before the constructor of Invoice. The eagle eyed among you will notice a regression in the code style as well: Customer is no longer passed in to the constructor at all, but is instead set via a modifier method. By doing this, it has been necessary to drop the final from the attribute definition as well. This is a bit of a step backwards, but I will come back to that later.

For now, though, you can see that you have made fairly minor changes overall to the class, but that the new @Inject is the most important thing to notice. This is a hint to Guice to "get involved" with the constructor of this class. It is still possible to create and use an instance this class just has you always have, but if Guice is used to create an instance, it proceeds as follows:

  1. It sees the @Inject annotation before the constructor.
  2. It looks at the type signature of the constructor parameters.
  3. For each of the parameters passed in to the constructor, it attempts to find a suitable implementation instance to pass in automatically for that parameter using a variety of rules.
  4. There is no Step 4. (Well, okay, there is, sort of—if Guice can't work out a concrete instance to pass in for a parameter, it will issue an error that, hopefully, will help you track down the problem.)

All this looks like magic, but it isn't; you just haven't completed your responsibilities yet. If Guice made this work as it stands, it would indeed be magic because you haven't given it enough information yet to know what to use for the TaxRateManager parameter. Beyond that, you haven't put it in control yet either (told Guice that you want it to do something). You'll look at those pieces next.

Binding Configuration

First up, explain to Guice what you want it to do when it sees a request to inject a TaxRateManager into something (remember that TaxRateManager is an interface, not a concrete implementation, so it has to create something real to use there).

To do this, you create a configuration module with a binding in it:

import com.google.inject.Binder;
import com.google.inject.Module;

public class TaxRateTestingModule implements Module {

   public void configure(Binder binder) {
      binder.bind(TaxRateManager.class).to(FakeTaxRateManager.class);
   }

}

That's it! This creates a specialization of Module that explains to Guice that when you see a TaxRateManager class, what you really want (at least for your testing purposes) is an instance of FakeTaxRateManager. In production, you could have another module that specified a DbTaxRateManager instead. This is where the auto-wiring blueprint comes from. Of course, a real system is likely to have a lot more such bindings defined, in which case you just need more binder.bind calls to define them. A lot of the errors you will see in a large Guice system are likely to be related to missing bindings, and hopefully the error reports are good enough to make it obvious which ones are missing.

One more quick thing: I mentioned earlier that using just a single instance of the TaxRateManager implementation would probably be a good idea, but that creating a typical static style singleton is too limiting (or too hard-wired) for good testing. Guice comes to your rescue here as well by providing a Singleton "scope" for your implementation binding. This can be applied two different ways:

One way is to add another call chained on to the binder.bind so it looks like this:

binder.bind(TaxRateManager.class).to(FakeTaxRateManager.class)
   .in(Scopes.SINGLETON);

where Scopes is another class imported from com.google.inject.

The other way (and the way used in the source code example) is to add an @Singleton annotation to the FakeTaxRateManager implementation:

@Singleton
public class FakeTaxRateManager implements TaxRateManager {

Both ways have advantages and disadvantages, and it's largely a matter of preference which one you will use. I prefer the latter way because it stores the semantic intent that the FakeTaxRateManager is a single instance in the system right there with the definition of the concrete class.

Go to page: Prev  1  2  3  4  5  Next  

Next article: Squeezing More Guice from Your Tests with EasyMock


Tools:
Add www.developer.com to your favorites
Add www.developer.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed


Enterprise Java Archives






internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers