11

I am getting a NullPointerException when I try to unit test some methods in a JDialog object. I have to initialize a mock version of the parent of the dialog as well as another class that will be used (in addition to calling a static method. The code is as follows:

@RunWith( PowerMockRunner.class )
@PrepareForTest( ControlFileUtilities.class )
public class StructCompDlgTest 
{
  @Before
  public void setUp() throws Exception
  {
    controlFrame    = org.mockito.Mockito.mock( ControlFrame.class );
    structCmpDlg    = new StructureCompareDialog( controlFrame );
    serverPipeline  = org.mockito.Mockito.mock( ServerPipeline.class );
  }
...
}

The code that is called for constructing the dialog is here:

StructureCompareDialog( IControlFrame controlFrame )
{
 super( (Frame) controlFrame, "title", true );
 ...
}

when the super constructor is called I will eventually get an NullPointerError at java.awt.Window.addOwnerWindow(Window.java:2525)"

void addOwnedWindow(WeakReference weakWindow) {
  if (weakWindow != null) {
    synchronized(ownedWindowList) {  ***<<------ offending line***
      // this if statement should really be an assert, but we don't
      // have asserts...
      if (!ownedWindowList.contains(weakWindow)) {
        ownedWindowList.addElement(weakWindow);
      }
    }
  }
}

I know I am mixing up statics and swing gui in a toxic swirl but I have no choice. I was given the instruction to throw together some unit tests with existing code. I have no idea what is going wrong.

Thanks

sldahlin
  • 685
  • 1
  • 8
  • 19
  • Did you ever get this working? If so, would you mind posting the solution? – glenneroo Feb 05 '13 at 14:44
  • Starnge you are getting null pointer at `synchronized(ownedWindowList)`. If you check `ownedWindowList` data member in Window.java, it has been instantiated and never assigned to null again. Wondering what could possibly make this data member null. Can you check in your code if this data member is accessed (using Reflection) and has been changed to null. Its least possible case that this data member needs to be changed manually but better to make sure. – Yogesh Ralebhat Feb 06 '13 at 06:05
  • @glenneroo, I think putting bounty here instead of creating new question with your own code was a mistake. Could you provide some details such as what you do and stack trace of exception(s) you get. – SergGr Mar 01 '17 at 00:41
  • @SergGr, You're probably right, my configuration is slightly different (no PowerMockRunner) but otherwise same exception and location. The stack trace doesn't seem very helpful but I will create another question and hope it doesn't get marked as a duplicate. – glenneroo Mar 03 '17 at 03:45
  • @glenneroo, actually it might be useful to add a link to this question and mention that you still got no solution for your issue. – SergGr Mar 03 '17 at 03:47

3 Answers3

5

Looks tricky! Essentially you're going to have to find all of the methods that are being called on controlFrame as part of the constructor, and then sprinkle some calls to

when(controlFrame.methodCalled()).thenReturn(somethingSensible);

If this is looking like a difficult chore, how about trying to create a default implementation of IControlFrame that you create as part of your test setUp() and using that instea of a mock.

I had a similar issue a while ago where I was trying to unit test a spring JMS listener. Rightly or wrongly, I got a working solution by creating my own default implementation of DefaultMessageListenerContainer which was giving me similar issues to what you are describing. My solution involved extending the real implementation with my own test specific version which looked like this

/**
 * Empty mocked class to allow unit testing with spring references to a
 * DefaultMessageListenerContainer. The functionality on this class should never be
 * called so just override and do nothing.  
 */
public class MockDefaultMessageListenerContainer extends DefaultMessageListenerContainer {

    public MockDefaultMessageListenerContainer() {
    }

    public void afterPropertiesSet() {
    }

    @Override
    protected Connection createConnection() throws JMSException {
        return null;
    }
}

In my example I was able to get my tests running by passing back a null value for the problemmatic createConnection() method. Perhaps the same approach can help you.

Brad
  • 15,186
  • 11
  • 60
  • 74
0

The ownedWIndowList is transient in the java.awt.Window class. Is your instance of the JDialog getting serialized? If so, you may need to use the readObject(java.io.ObjectStream) method from the Serializable interface to re-initialize the ownedWIndowList

Jayfray
  • 415
  • 3
  • 12
0

I don't know what your IControlFrame looks like, but passing a mocked Frame to super() doesn't work. I had to instantiate my own version:

private class EmptyControlFrame extends JFrame implements IControlFrame {

    @Override
    public JFrame getFrame() {
        return null;
    }

    // return null for any other overrides from IControlFrame
}

Then in your setUp():

controlFrame = new EmptyControlFrame();
glenneroo
  • 1,908
  • 5
  • 30
  • 49