views:

342

answers:

3

I'm trying to test that I'm throwing an exception when appropriate. In my test class I have a method similar to the following:

public void testParseException() {

    try {
        ClientEntitySingleton.getInstance();
        fail("should have thrown exception.");
    } catch (RuntimeException re) {
        assertEquals(
            "<exception message>",
            re.getMessage());
    }
}

This works fine (green bar) whenever I run that single unitTest class. However, when I add that test to a testSuite, I get a red bar Unit test failure reported on the exception.

One more thing... it works in the testSuite, if it's the first test in the suite. Actually, I'm doing two of these tests and just figured out that if I make them the first two tests in the suite, all is good, but I get this failure if a "regular" test precedes it. So I have a work-around, but no real answer.

Any ideas?

Heres'a stack trace of the "failure"

java.lang.RuntimeException: ProcEntity client dn="Xxxxxx/Xxxx/XXX" is defined multiple times. at com.someco.someprod.clientEntityManagement.ClientEntitySingleton.addClientEntity(ClientEntitySingleton.java:247) at com.someco.someprod.clientEntityManagement.ClientEntitySingleton.startElement(ClientEntitySingleton.java:264) at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanStartElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) at org.apache.xerces.parsers.XMLParser.parse(Unknown Source) at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) at com.someco.someprod.clientEntityManagement.ClientEntitySingleton.parse(ClientEntitySingleton.java:216) at com.someco.someprod.clientEntityManagement.ClientEntitySingleton.reload(ClientEntitySingleton.java:303) at com.someco.someprod.clientEntityManagement.ClientEntitySingleton.setInputSourceProvider(ClientEntitySingleton.java:88) at com.someco.someprod.clientEntityManagement.test.TestClientBase.setUp(TestClientBase.java:17) at com.someco.someprod.clientEntityManagement.test.TestClientEntityDup.setUp(TestClientEntityDup.java:8) at junit.framework.TestCase.runBare(TestCase.java:125) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at junit.framework.TestSuite.runTest(TestSuite.java:208) at junit.framework.TestSuite.run(TestSuite.java:203) at junit.framework.TestSuite.runTest(TestSuite.java:208) at junit.framework.TestSuite.run(TestSuite.java:203) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

+2  A: 

Without seeing the rest of the code it's difficult to tell, but are there other tests that are using ClientEntitySingleton and calling its getInstance method? If you have a lazy init singleton, then it wouldn't be being initialized multiple times.

Have you tried forking the tests into a separate JVM and see if you still have the problem?

Jeff Storey
I've considered that there is something residual about the singleton, but it remains that in both cases, the code is throwing the exception. When run alone it hits my catch clause and executes the assertEquals, while, when it's part of a testSuite it never makes it to the assertEquals. JUnit just catches the exception and reports the exception itself as a test failure.
Mike Cargal
Is there a non RuntimeException being thrown when it's part of a test suite (again maybe an effect from the singleton)? Maybe initializing the singleton multiple times is actually causing an exception. Since you're only catching RuntimeException, a non RuntimeException would show up in the test suite and reported by the test runner.
Jeff Storey
It's the same RuntimeException that I'm throwing on purpose (and that I catch in the test when it's stand alone). In the testSuite JUnit gets to it before my catch clause and calls it a test failure. Very odd.
Mike Cargal
Hmm..that sounds strange. Is there any way you could post the stack trace of the test failure?
Jeff Storey
added to the question
Mike Cargal
In looking at that stack trace, I don't see the call to ClientSingleton.getInstance(). It actually looks like the exception is occurring as a result of the setup method. Do you have multiple tests in that class that are order dependent? Your IDE and test suite runner may run them in different orders. If you have multiple tests, try ignoring all but this one, then re-enable them one by one until the problem occurs.
Jeff Storey
That's it!!!When I run it stand-alone, the call to getInstance() triggers the parsing. Once I have the singleton, the call to set the inputprovider (that's done as part of the setup()), triggers the parsing, so it's not inside my try/catch.Thanks!!
Mike Cargal
No problem at all.
Jeff Storey
I added code to the tearDown() method to clean out the singleton. That did the trick, there is no more dependency on order and the test work correctly stand-alone and as part of a testSuite
Mike Cargal
Obligatory link to http://misko.hevery.com/2008/08/17/singletons-are-pathological-liars/
matt b
A: 

I would suggest that you do not catch RuntimeException, which has about a thousand subclasses.

Based on the name of your class, it sounds as if you are only expecting ParseException. This is what you should be catching in your test.

Finally, assuming that you are running these tests in an IDE (because of the references to red/green bars), you should examine the failure message of the case - JUnit should report what the expected message was versus what the actual message is. This will help you diagnose what is actually going on, which should help you figure out why you might get one type of behavior when the test is run isolated vs run as a group.

matt b
Actually, it is throwing a RuntimeException (not a subclass). THe error I get is not a mismatch on the assertEquals, but just a test failure that the exception was raised. It works just fine, running the assertEquals, when run alone. It only fails when it's made part of a testSuite
Mike Cargal
I will try subclassing RuntimeException, throwing the subclass and catching it explicitly (it was a bit "lazy" just throwing RuntimeException). I'm not sure why that should make a difference, but I'm also not sure why I'm seeing the difference when I add it to the testSuite. So, it's worth a shot.
Mike Cargal
just added more detail re: the impact of the ordering of the tests in the testSuite.
Mike Cargal
A: 

Just realized that I never posted the "answer" to this problem.

The ClientEntitySingleton was set up so that on initialization, it would simply cache the name of the xml file to be loaded. It is loaded on first reference, and it is reloaded if you change the file name once the singleton data is loaded.

So, as long as the failures occurred before a successful load, the parse took place during the test case (1st access). Once I had successfully loaded an XML file, any future changes to the source file property triggered an immediate parse of the XML file. Unfortunately, I was setting the file name in the test setup method. (That's actually right there in the stack trace.)

So, if you think JUnit is not working with testing exceptions, this isn't your confirmation.

Mike Cargal