Create a gist now

Instantly share code, notes, and snippets.

Stupid singleton is stupid
public class UsesLongRunningCtor {
/** Retrieves data and returns processed result. */
public String transformData() {
// LongRunningCtor "embedded"; direct reference, like a static utility class.
String rawData = LongRunningCtor.instance().fetch();
return rawData.replace("Raw", "Processed");
}
}
/** Pseudo-singleton with a slow constructor. Don't make singletons like this. */
public class LongRunningCtor {
private static final LongRunningCtor INSTANCE = new LongRunningCtor();
private LongRunningCtor() {
try { Thread.sleep(60 * 1000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
public String fetch() { return "Raw data"; }
public static LongRunningCtor instance() { return INSTANCE; }
}
/** Slow test is slow. Calls undecorated singleton. */
@Test
public void testSlowSingleton() {
long start = System.currentTimeMillis();
UsesLongRunningCtor underTest = new UsesLongRunningCtor();
assertEquals("Processed data", underTest.transformData());
long end = System.currentTimeMillis();
out.println("Unmocked test time ~" + (end - start) / 1000.0 + " seconds.");
}
// Output is ~ "Unmocked test time ~60.0 seconds."
@RunWith(PowerMockRunner.class)
@PrepareForTest(LongRunningCtor.class)
public class TestWithoutCtor {
@Test
public void testSlowSingleton() {
long start = System.currentTimeMillis();
// Suppress ctor *before* createPartialMock and static mock, or ctor is run.
suppress(constructor(LongRunningCtor.class));
// Could also do mockStaticPartial(LongRunningCtor.class, "instance").
mockStatic(LongRunningCtor.class);
// Could also do createPartialMock(LongRunningCtor.class, "fetch").
LongRunningCtor mock = createMock(LongRunningCtor.class);
expect(LongRunningCtor.instance()).andReturn(mock);
expect(mock.fetch()).andReturn("Processed data");
replayAll(mock);
UsesLongRunningCtor underTest = new UsesLongRunningCtor();
assertEquals("Processed data", underTest.transformData());
long end = System.currentTimeMillis();
verify(mock);
out.println("Unmocked test time ~" + (end - start) / 1000.0 + " seconds.");
}
}
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-easymock</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.1</version>
</dependency>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment