August 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Squeezing More Guice from Your Tests with EasyMock

  • July 12, 2007
  • By Dick Wall
  • Send Email »
  • More Articles »

Enter EasyMock

The answer lies in using a Mock object. There are several such libraries available for Java; a popular one is EasyMock and is the one you will look at in this article.

EasyMock is brilliant. It allows you to take an interface definition and create an instance of a mock object that conforms to the methods of that interface. It then lets you script up what you are expecting to be called on that interface, what it should return, and any exceptions it should throw. You then replay the script, run your test, and at the end you can validate that everything was called as expected and the exact number of times expected. Too many calls, or the wrong calls, or even too few calls (something expected that was never invoked) will cause an error during the validation stage. If this is not yet clear, don't worry; there is an example below that should illustrate all this much better.

By using EasyMock to implement any objects that your class calls, you can therefore test not only the calls in to the class, but also anything it calls out to—literally testing all sides of your class.

See how you use EasyMock to create an injectable instance of a mock object. In your TaxRateTestingModule class, you can create the instance of the mock object you want to use, and then bind it to the TaxRateManager interface with Guice:

import com.google.inject.Binder;
import com.google.inject.Module;
import org.easymock.EasyMock;

public class TaxRateTestingModule implements Module {

   public void configure(Binder binder) {
      TaxRateManager mockTaxRateManager =
         EasyMock.createMock(TaxRateManager.class);
      binder.bind(TaxRateManager.class).toInstance(mockTaxRateManager);
   }
}

To use this, you will need to download EasyMock and add the easymock.jar to your project libraries. This will allow you to import org.easymock.EasyMock. You then can use the static method createMock from this class to create a mock object using the TaxRateManager interface. This is then bound to the TaxRateManager in Guice using the binder method "toInstance()".

Now, see how to obtain and use the easymock instance in a test:

@Test
public void getTotalWithTax() throws Exception {
   System.out.println("getTotalWithTax");

   Customer customer = new Customer(CUST2_ID, "FredCo");
   EasyMock.expect(taxRateManager.getTaxRateForCustomer(customer))
      .andReturn(new BigDecimal(6.25));

   EasyMock.replay(taxRateManager);

   Invoice invoice = invoiceFactory.createInvoiceForCustomer(customer);

   double expResult = 106.25;    // Expected total with tax

   // add some line items
   invoice.addItem("Beach Ball",
                   "Beach Ball in Multiple Colors", 37.55);
   invoice.addItem("Swimsuit", "Fashionable swimsuit, black", 62.45);

   BigDecimal result = invoice.getTotalWithTax();

   assertEquals(expResult, result.doubleValue());

   EasyMock.verify(taxRateManager);
}

EasyMock has been imported again into this class, and just as before taxRateManager has been injected into the test as well (the easymock instance is injected by the TaxRateTestingModule). The easymock object conforms perfectly to the TaxRateManager interface, but when used in conjunction with static methods on EasyMock, it can do ever so much more.

The line:

EasyMock.expect(taxRateManager.getTaxRateForCustomer(customer))
   .andReturn(new BigDecimal(6.25));

does what it sounds like—it actually scripts up the expected interaction for the easymock instance. In this case, it literally says "Expect the getTaxRateForCustomer method to be called with the customer instance, and when that happens return the value 6.25 as a BigDecimal."

The next line tells EasyMock to switch from the "recording" mode where you are telling it what to expect into replay mode, where the interaction we have scripted up should be followed.

The test then calls getTotalWithTax that turns around and calls getTaxRateForCustomer on the easymock instance, which true to the script returns 6.25 as the answer. You assert that the value comes back for the total with tax. As a final step, you call a "verify()" method on the taxRateManager instance that makes sure that all of the expected calls were actually made.





Page 3 of 5



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel