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 spaceIt 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.
