Software QA FYI - SQAFYI

Guicing Up Your Testing

By: Dick Wall

In what I hope will be the first of several articles about Guice, a new lightweight dependency injection container from Bob Lee and Kevin Bourrillion from Google, this article examines the simplest and most obvious use case for the Guice container, for mocking or faking objects in unit tests. In future articles I will examine other, more ambitious areas where it can be used, including dependency elimination in large code bases.

If you are familiar with the idea of mock or fake objects, this article may seem like slow going (apart from the Guice parts, hopefully). However, if you have not used mock or fake objects before, this article will not only cover their use, but demonstrate how these techniques go hand-in-hand with dependency injection.

The Test Case
To illustrate the use of Guice, you need an example unit testing setup. I settled on something pretty simpleóan invoice class that uses a sales tax rate manager (another object) to look up a sales tax percentage for a customer. The invoice then adds it on to the total sum of the line item costs in the invoice.

The twist is, you are going to pretend that the tax rate manager looks up the tax rate for a customer based on the customer ID (say it varies depending on their state, which is information that the tax rate manager gets from the customer ID). You'll also throw in there that the poor old database backing this tax rate lookup is overloaded, and takes around five seconds for any query or update operation (this really isn't much of a stretch for a large and heavily used databaseóbelieve me).

Your test objects might look something like this:




public class Invoice {

   /** A Simple public inner and immutable class to hold line items
    * for the invoice, including the title, description and cost
    */

   public class Item {
      private final String title;
      private final String description;
      private final BigDecimal cost;

      .... (constructors and getters here)
   }

   private final Customer customer;
   private List lineItems;
   private final DbTaxRateManager taxRateManager;

   public Invoice(Customer customer) {
      this.customer = customer;
      // set up the line item list
      this.lineItems = new ArrayList();
      this.taxRateManager = DbTaxRateManager.getTaxRateManager();
   }

   public void addItem(String title, String description, double amount) {
      lineItems.add(new Item(title, description, amount));
   }

   private BigDecimal getTotal() {
      BigDecimal runningTotal = new BigDecimal(0);
      for (Item item:lineItems) {
         runningTotal = runningTotal.add(item.cost);
      }
      return runningTotal;
   }


   public BigDecimal getTotalWithTax() {
      BigDecimal total = this.getTotal();

      // now find the tax rate for the customer
      BigDecimal taxRate =
      this.taxRateManager.getTaxRateForCustomer(
         customer.getCustomerId());

      // and calculate the taxed total
      BigDecimal multiplier = taxRate.divide(new BigDecimal(100));

      // Boy, Big Decimal might be accurate, but it certainly is
      // ugly to do math with...
      return total.multiply(multiplier.add(new BigDecimal(1)));

   }
}

Full article...


Other Resource

... to read more articles, visit http://sqa.fyicenter.com/art/

Guicing Up Your Testing