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.



Post a Comment:
Comments are closed for this entry.