Verify EasyMock Behavior When Expecting Exceptions
Posted on May 13, 2008 by Scott Leberknight
Often when writing unit tests I use EasyMock to mock dependencies of the class under test. And many times I need to test that a certain type of exception is thrown during a test. Sometimes I need both, for example I am using a mock to simulate a dependency that throws an exception and I want my test to verify the appropriate exception was indeed thrown and that the mock was called properly. In those cases, I use a simple little trick: use a try/finally block along with a JUnit "@Test(expected = FooException.class" annotation on my test method. Voila! Now you can verify mock behavior and verify the exception was thrown at the same time. This is cleaner than using a catch block and asserting the correct exception was thrown, since you rely on JUnit to verify the exception using the "expected" attribute of the @Test annotation. For example:
@Test(expected = ThrottleException.class)
public void testSomethingWithDependencies() {
// Create mock
Rocket mainBooster = createMock(Rocket.class);
// Record behavior
mainBooster.ignite();
// Simluate an invalid call to 'throttleUp'
expect(rocket.throttleUp(-10000L)).andThrow(ThrottleException.class);
// Replay mock
replay(rocket);
// Create object with dependency on mainBooster
SpaceShuttle shuttle = new SpaceShuttle(rocket);
// Now try to perform a 'blast off' and
// verify the mock behavior was as expected
try {
shuttle.blastOff();
}
finally {
verify(rocket);
}
}
If instead of writing tests in Java you write them in Groovy, the above code could be a little bit Groovier, though not much. (In an earlier post I showed how you can write unit tests in Groovy and still use JUnit instead of GroovyTestCase if you like.)
@Test(expected = ThrottleException)
void testSomethingWithDependencies() {
// Create mock
def mainBooster = createMock(Rocket)
// Record behavior
mainBooster.ignite()
// Simluate an invalid call to 'throttleUp'
expect(rocket.throttleUp(-10000L)).andThrow(ThrottleException.class)
// Replay mock
replay rocket
// Create object with dependency on mainBooster
def shuttle = new SpaceShuttle(rocket)
// Now try to perform a 'blast off' and
// verify the mock behavior was as expected
try {
shuttle.blastOff()
}
finally {
verify rocket
}
}
Even more Groovy in this case would be to extend GroovyTestCase and use its shouldFail method, like so:
void testSomethingWithDependencies() {
// Create mock
def mainBooster = createMock(Rocket)
// Record behavior
mainBooster.ignite()
// Simluate an invalid call to 'throttleUp'
expect(rocket.throttleUp(-10000L)).andThrow(ThrottleException.class)
// Replay mock
replay rocket
// Create object with dependency on mainBooster
def shuttle = new SpaceShuttle(rocket)
// Now try to perform a 'blast off' and
// verify the mock behavior was as expected
shouldFail(ThrottleException) {
shuttle.blastOff()
}
verify rocket
}
The GroovyTestCase version is probably the cleanest of the above three options. If you're not into Groovy, you can still use the JUnit "@Test(expected = BarException.class)" together with a try/finally/verify in plain Java unit tests for a cleaner test experience.