hprange / wounit

The WOUnit framework contains a set of utilities for testing WebObjects applications using JUnit 4.7 or later capabilities.
http://hprange.github.io/wounit/
Apache License 2.0
19 stars 18 forks source link

NPE from TemporaryEditingContext.fixJavaMemoryDictionary #16

Closed paulhoadley closed 12 years ago

paulhoadley commented 13 years ago

I have what I think is a very basic unit test using a TemporaryEditingContext. I create the TemporaryEditingContext using an @Rule annotation, load it up with a few EOs, saveChanges(), and then run the code under test using those EOs. This works fine in Eclipse, but I can't get it to run outside Eclipse using Hudson and Ant. Specifically, I get a NullPointerException during creation of the TemporaryEditingContext:

java.lang.NullPointerException
    [junit]     at com.wounit.rules.TemporaryEditingContext.fixJavaMemoryDictionary(TemporaryEditingContext.java:147)
    [junit]     at com.wounit.rules.TemporaryEditingContext.<init>(TemporaryEditingContext.java:80)
    [junit]     at net.logicsquad.webobjects.core.test.LSWOCSVUtilsTest.<init>(Unknown Source)
    [junit]     at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

The issue is in this method:

private void fixJavaMemoryDictionary() {
    NSBundle bundle = NSBundle.bundleForName("JavaMemoryAdaptor");

    bundle._infoDictionary().takeValueForKey(ERMemoryAdaptor.class.getName(), "EOAdaptorClassName");
}

I actually had this error come up initially in Eclipse, and it was because I didn't have JavaMemoryAdaptor.framework on the build path. Outside of Eclipse, running ant -v shows that it is on the classpath for this test, though.

Any thoughts?

paulhoadley commented 13 years ago

I've got the WOUnit source up and running in Eclipse now, so I can make some moves towards debugging this. I can confirm a couple of things:

  1. Simply not calling fixJavaMemoryDictionary() is not a solution. The Javadoc comments for that method made me wonder if it was only an issue in a Maven build setting, but apparently not. Commenting out the call to fixJavaMemoryDictionary() causes this error:

Unable to get the name of the class to instantiate for the adaptor framework JavaMemoryAdaptor. The possible causes for this error are: the adaptor framework is not installed on your system, the adaptor framework is not linked into your application, or the info dictionary for this adaptor is corrupted.

  1. bundle is null after line 145:
NSBundle bundle = NSBundle.bundleForName("JavaMemoryAdaptor");
paulhoadley commented 13 years ago

There's some kind of bundle loading problem going on when the tests are run outside Eclipse, whether under Hudson or just via Ant on the command line. When I get fixJavaMemoryDictionary() to dump a list of the framework bundles loaded, I get a list of everything I would expect when run inside Eclipse: PostgresqlPlugIn, JavaEOAccess, JavaEOControl, ..., JavaMemoryAdaptor. On the command line, I get a single framework listed, LSWOCore, which is the name of the framework containing the tests I am running. This framework isn't even listed when run inside Eclipse.

Obviously there is a load of fairly precarious setup involved in creating the Hudson workspace where the build and testing takes place, and it's going to be hard for anyone else to reproduce this, I suppose. It's really not clear to me why NSBundle doesn't seem to be able to find any bundles, even though all the JARs are listed on the classpath, though.

paulhoadley commented 13 years ago

I'm getting there really slowly... As I not above, setting all this up for Hudson is somewhat precarious, and a pain to test, but what I forgot was setting the dir attribute (and fork) on the junit task in build.xml:

<junit haltonfailure="false" fork="true" dir="${dest.dir}/${project.name}.framework" printsummary="true" failureproperty="test.failed">

That was my blunder, and it's somewhat embarrassing because I solved that problem in other projects long ago. But it's not quite the whole solution. Now, NSBundle finds LSWOCore, as above (the main bundle), and JavaEOAccess, JavaEOControl and so on, but not any of the Wonder frameworks, and in particular I obviously need JavaMemoryAdaptor. So NSBundle apparently can't find anything in workspace/Root/Library/Frameworks, despite supplying ant with -propertyfile Root/wolips.properties on the command line, which contains, among others, the following line:

wo.local.frameworks=/Users/paulh/.hudson/jobs/LSWOCore/workspace/Root/Library/Frameworks

I am almost completely stumped.

paulhoadley commented 13 years ago

I promise to stop talking to myself after this post. I think my Hudson workspace and test environment are working as designed. I've just thrown a couple of lines into another test class in the same suite (which incidentally doesn't touch WOUnit), and NSBundle.frameworkBundles() dumps a list of all the bundles I was expecting, including Wonder frameworks, and including JavaMemoryAdaptor. So I'm beginning to think that fixJavaMemoryDictionary() is being called too early during setup? Does this sound plausible?

hprange commented 12 years ago

Hi Paul,

Sorry for the long time to answer. Would you mind to send me a sample project?

paulhoadley commented 12 years ago

Hi Henrique,

No problem. I will try and put something together soon.

hprange commented 12 years ago

Good news. I've found the culprit. The solution for issue #13 has a side effect. The bad news, I still haven't found a good solution. I'm writing to the WebObjects list with more details about the problem.

paulhoadley commented 12 years ago

Very good news. Let me know if I can help in debugging or testing it.