EasyMock and OutOfMemoryError: PermGen space
I wrote a test using the easy-to-use EasyMock Unit-testing API:package com.publicobject.pizzadelivery;
import junit.framework.TestCase;
import org.easymock.classextension.EasyMock;
public class PizzaDeliveryPersonTest extends TestCase {
private PizzaStore pizzaStore;
private Customer customer;
private Order order;
private Address address;
private DeliveryPerson deliveryPerson;
@Override
public void setUp() {
pizzaStore = EasyMock.createMock(PizzaStore.class);
order = EasyMock.createMock(Order.class);
address = EasyMock.createMock(Address.class);
customer = EasyMock.createMock(Customer.class);
EasyMock.expect(pizzaStore.getNextOrder())
.andReturn(order).anyTimes();
EasyMock.expect(order.getAddress())
.andReturn(address).anyTimes();
EasyMock.expect(order.getPrice())
.andReturn(new Money(17)).anyTimes();
EasyMock.expect(address.getCoordinates())
.andReturn(new GpsCoordinates(30, 40)).anyTimes();
EasyMock.expect(customer.acceptOrder(order))
.andReturn(new Money(20).anyTimes();
EasyMock.replay(pizzaStore);
EasyMock.replay(order);
EasyMock.replay(address);
EasyMock.replay(customer);
}
public void testDeliveryPerson() {
doTestDeliveryPerson(new BasicPizzaDeliveryPerson());
}
public void testDeliveryPersonWithNoGasInCar() {
BasicPizzaDeliveryPerson deliveryPerson = new BasicPizzaDeliveryPerson()
deliveryPerson.getCar().setFuel(0);
doTestDeliveryPerson(deliveryPerson);
}
public void testDeliveryPersonWhoSpeaksFrench() {
BasicPizzaDeliveryPerson deliveryPerson = new BasicPizzaDeliveryPerson()
deliveryPerson.setNativeLanguage(Language.FRENCH);
doTestDeliveryPerson(deliveryPerson);
}
public void testRealTimeDeliveryPerson() {
PizzaDeliveryPerson deliveryPerson = new RealTimePizzaDeliveryPerson()
doTestDeliveryPerson(deliveryPerson);
}
public void testMinimumWageDeliveryPerson() {
BasicPizzaDeliveryPerson deliveryPerson = new BasicPizzaDeliveryPerson()
deliveryPerson.setHourlyWage(new Money(7));
doTestDeliveryPerson(deliveryPerson);
}
public void doTestDeliveryPerson(PizzaDeliveryPerson deliveryPerson) {
assertTrue(deliveryPerson.getTotalMoney().toDollars() == 0);
deliveryPerson.setStore(pizzaStore);
deliveryPerson.runDelivery();
assertTrue(deliveryPerson.getTotalMoney().toDollars() == 20);
assertTrue(deliveryPerson.getTotalTips().toDollars() == 3);
}
}
...but when I ran it in my continuous build, it failed due to a memory leak:
java.lang.OutOfMemoryError: PermGen space
It turns out that every time I call
EasyMock.createMock()
*, a piece of memory is allocated that can never be reclaimed!My hacky fix was to make all the mocked objects
static
. Now they only get created once, not once for each of the 5 test methods:public class PizzaDeliveryPersonTest extends TestCase {
private static PizzaStore pizzaStore;
private static Customer customer;
private static Order order;
private static Address address;
private static DeliveryPerson deliveryPerson;
static {
pizzaStore = EasyMock.createMock(PizzaStore.class);
order = EasyMock.createMock(Order.class);
address = EasyMock.createMock(Address.class);
customer = EasyMock.createMock(Customer.class);
EasyMock.expect(pizzaStore.getNextOrder())
.andReturn(order).anyTimes();
EasyMock.expect(order.getAddress())
.andReturn(address).anyTimes();
EasyMock.expect(order.getPrice())
.andReturn(new Money(17)).anyTimes();
EasyMock.expect(address.getCoordinates())
.andReturn(new GpsCoordinates(30, 40)).anyTimes();
EasyMock.expect(customer.acceptOrder(order))
.andReturn(new Money(20).anyTimes();
EasyMock.replay(pizzaStore);
EasyMock.replay(order);
EasyMock.replay(address);
EasyMock.replay(customer);
}
...
}
It gets the job done, but not well. The disadvantages of this approach:
anyTimes()
on my objects so their methods can be called repeatedlyIt would be a great fix for EasyMock if multiple calls to
EasyMock.createMock(PizzaStore.class)
could share the same generated class object.