Here's a fun little false positive I ran into recently.
Application (ClassBeingTested) believes Library (ClassBeingMocked) throws an exception, but Library really does not. Yet Application's unit-test case passes! This takes an interplay of JUnit, Jmock, and their use of reflection.
Library:
public interface ClassBeingMocked { public void neverThrowsAnException(); } public class ClassBeingMockedImpl implements ClassBeingMocked { public void neverThrowsAnException() { System.out.println("ClassBeingMocked: in the method which does not throw an exception"); } }
Application:
public class ClassBeingTested { private final ClassBeingMocked _them; public ClassBeingTested(ClassBeingMocked them) { _them = them; } public void neverThrowsAnExceptionEither() { try { _them.neverThrowsAnException(); } catch (Exception e) { System.out.println("ClassBeingTested#neverThrowsAnExceptionEither: " + "caught \"" + e.toString() + "\""); } } }
Test code:
public class MyTest { private Mockery _mockery; private ClassBeingMocked _mockedInstance; private ClassBeingTested _testedInstance; @Before public void setup() { _mockery = new Mockery(); _mockedInstance = _mockery.mock(ClassBeingMocked.class); _testedInstance = new ClassBeingTested(_mockedInstance); } @Test public void testMethod() { _mockery.checking(new Expectations() {{ one(_mockedInstance).neverThrowsAnException(); will(throwException(new Exception("we expect an exception on timeout"))); }}); _testedInstance.neverThrowsAnExceptionEither(); _mockery.assertIsSatisfied(); } }
What prints is:
JUnit version 4.10 ..ClassBeingTested#neverThrowsAnExceptionEither: caught "java.lang.IllegalStateException: tried to throw a java.lang.Exception from a method that throws no exceptions" Time: 0.021 OK (4 tests)
One handy item is the print to stdout in the application's exception handler; without that, the misunderstanding proceeds silently. Yet this will disappear in logging contexts.
One solution is a narrower catch: If the application instead does
try { _them.neverThrowsAnException(); } catch (MoreSpecificExceptionType e) { ... }
then this is caught at compile time:
"exception MoreSpecificExceptionType is never thrown in body of corresponding try statement"This must be used carefully in a catch-all-exceptions server-thread context.
No comments:
Post a Comment