Zach's Blog

Just another WordPress.com weblog

Posts Tagged ‘easymock

ActiveObjects + EasyMock + Guice

leave a comment »

In the last post we saw how using Guice for dependency injection and EasyMock for mock objects produces a well-designed system that is easy to unit test.  In this post I’ll describe how the ActiveObjects ORM fits in nicely with these other tools.

When using ActiveObjects, each database table is represented by a Java interface, called an entity.  Each column in the database corresponds to get/set methods in the interface.  Individual rows in the table correspond to instances of the interface.  For example, here is a very simple AO entity for a restaurants table:

import net.java.ao.*;

public interface Restaurant extends Entity
{
    public String getName();
    public void setName(String name);

    public String getAddress();
    public void setAddress(String address);

    public String getPhone();
    public void setPhone(String phone);

    public int getTableCount();
    public void setTableCount(int tableCount);
}

Since every entity is an interface, they are incredibly easy to mock.  We saw this in the last example, where the Restaurant object was mocked and then we specified an expectation for its getName() method:

public class ShareTest
{
    private Share share;
    private Twitter twitter;
    private Restaurant restaurant;
    private Credentials credentials;

    @Before
    public void setup()
    {
        twitter = createMock(Twitter.class);
        restaurant = createMock(Restaurant.class);
        credentials = new Credentials("username", "password");
        share = new Share(twitter, credentials);
    }

    @Test
    public void testShare()
    {
        expect(restaurant.getName()).andReturn("Mucho Burrito");
        twitter.update(credentials, "I loved eating at Mucho Burrito!");

        replay(restaurant, twitter);
        share.share(restaurant);
        verify(restaurant, twitter);
    }
}

In a strict definition of unit testing, you should not be accessing a database at all.  The code that you are testing should be completely isolated from everything around it.  By mocking the AO entities in our code, we do not have to deal with databases at all in our unit tests.  (Testing your code with a database is also a good idea though – for that I recommend DbUnit).

AO provides a class called EntityManager that you use to create new entities or query the database for existing entities.  While you can mock an EntityManager using the EasyMock Class Extension in your unit tests, I actually create an IEntityManager interface that duplicates EntityManager’s API, along with a few extra convenience methods.  Any class that needs to create or find entities gets an instance of IEntityManager injected to its constructor (via Guice, of course).  The unit tests for that class then just mock the IEntityManager and pass it into the constructor when creating the instance in the setup() method.

In our restaurant review site, we want to provide a way for users to add new restaurants to the system.  On the back-end we need to take the user’s input (from an HTML form submit) and create a new Restaurant entity.  Let’s assume we use the following class to create a new restaurant:

import com.google.inject.*;

public class CreateRestaurant
{
    private IEntityManager manager;

    @Inject
    public CreateRestaurant(IEntityManager manager)
    {
        this.manager = manager;
    }

    public void create(String name, String address, String phone, int tableCount) throws SQLException
    {
        Restaurant restaurant = manager.create(Restaurant.class);
        restaurant.setName(name);
        restaurant.setAddress(address);
        restaurant.setPhone(phone);
        restaurant.setTableCount(tableCount);
        restaurant.save();
    }
}

Unit testing this class is a simple matter of mocking IEntityManager and Restaurant entities and asserting that proper methods are called on them in the create() method:

import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;
import java.sql.*;
import org.junit.*;

public class CreateRestaurantTest
{
    private IEntityManager manager;
    private Restaurant restaurant;
    private CreateRestaurant creator;

    @Before
    public void setUp() throws Exception
    {
        manager = createMock(IEntityManager.class);
        restaurant = createMock(Restaurant.class);
        creator = new CreateRestaurant(manager);
    }

    @Test
    public void testCreate() throws SQLException
    {
        String name = "Mucho Burrito";
        String address = "50 Mapleview Dr W Barrie, ON L4N 9H5";
        String phone = "(705) 739-6824";
        int tableCount = 15;

        expect(manager.create(Restaurant.class)).andReturn(restaurant);
        restaurant.setName(name);
        restaurant.setAddress(address);
        restaurant.setPhone(phone);
        restaurant.setTableCount(tableCount);
        restaurant.save();

        replay(manager, restaurant);
        assertSame(restaurant, creator.create(name, address, phone, tableCount));
        verify(manager, restaurant);
    }
}

Again, we exploited the fact that the CreateRestaurant class only uses instances of AO interfaces to make unit testing extremely simple & contained.

import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;

import java.sql.*;

import org.junit.*;

import com.pongr.ao.*;

public class CreateRestaurantTest
{
private IEntityManager manager;
private Restaurant restaurant;
private CreateRestaurant creator;

@Before
public void setUp() throws Exception
{
manager = createMock(IEntityManager.class);
restaurant = createMock(Restaurant.class);
creator = new CreateRestaurant(manager);
}

@Test
public void testCreate() throws SQLException
{
String name = “Mucho Burrito”;
String address = “50 Mapleview Dr W Barrie, ON L4N 9H5″;
String phone = “(705) 739-6824″;
int tableCount = 15;
expect(manager.create(Restaurant.class)).andReturn(restaurant);
restaurant.setName(name);
restaurant.setAddress(address);
restaurant.setPhone(phone);
restaurant.setTableCount(tableCount);
restaurant.save();

replay(manager, restaurant);
assertSame(restaurant, creator.create(name, address, phone, tableCount));
verify(manager, restaurant);
}
}

Written by Zach Cox

June 8, 2009 at 11:28 am

Posted in Java

Tagged with , ,

Guice + EasyMock = Flexible Testable Code

leave a comment »

Dependency injection and mock object testing are great practices on their own.  When used together your code ends up being very flexible and testable.  In this article we’ll use Guice and EasyMock.

When you design your system to use DI you end up with lots of interfaces that provide specific services, concrete implementations of those interfaces, and classes that depend on those interfaces.  Let’s pretend we’re building a web app that lets users find restaurants in their area and write reviews for them.  One little feature we just added lets the user share their love for a particular restaurant on Twitter.  There are several Java libraries for the Twitter API but we want our code to be really simple and not depend on any specific library.  Thus we create the Twitter interface (and a concrete implementation that wraps one of those Twitter Java libraries):

public interface Twitter
{
    public void update(Credentials credentials, String status);
}

Next we create the class that does the sharing.  This would probably respond to some kind of AJAX call from the browser – the specifics don’t really matter here.  The important thing is that we’re using Guice to inject two dependencies into this class’s constructor: a Twitter object that wraps some Twitter Java library, and a Credentials object that stores the current user’s Twitter username and password or OAuth tokens.

public class Share
{
    private Twitter twitter;
    private Credentials credentials;

    @Inject
    public Share(Twitter twitter, Credentials credentials)
    {
        this.twitter = twitter;
        this.credentials = credentials;
    }

    public void share(Restaurant restaurant)
    {
        twitter.update(credentials, "I loved eating at " + restaurant.getName() + "!");
    }
}

To properly unit test this class we really don’t want to be making real HTTP requests to Twitter’s API and then use their API to assert that the user’s status was actually updated with the correct content (that would be more of an integration test).

Instead we should completely isolate this Share class from everything around it, control the inputs to it and assert that is performing the correct behavior.  This is where mock objects come in handy.

public class ShareTest
{
    private Share share;
    private Twitter twitter;
    private Restaurant restaurant;
    private Credentials credentials;

    @Before
    public void setup()
    {
        twitter = createMock(Twitter.class);
        restaurant = createMock(Restaurant.class);
        credentials = new Credentials("username", "password");
        share = new Share(twitter, credentials);
    }

    @Test
    public void testShare()
    {
        expect(restaurant.getName()).andReturn("Mucho Burrito");
        twitter.update(credentials, "I loved eating at Mucho Burrito!");

        replay(restaurant, twitter);
        share.share(restaurant);
        verify(restaurant, twitter);
    }
}

Because we followed proper DI principles and hid the Twitter Java library behind an interface, we can easily provide our own mock Twitter object and totally control it (so no HTTP requests are made).  We use EasyMock in the setup() method to create the mock Twitter object and give it to the new Share object.  Then in the testShare() method we specify the calls we expect on our mocks and call the share() method.

Just by using DI with interfaces and constructor injection, we made our Share class easy to test.  EasyMock then gave us a great way to create the mock objects that isolate the Share class from its dependencies and properly unit test it.

Written by Zach Cox

June 1, 2009 at 12:42 pm

Follow

Get every new post delivered to your Inbox.