Powermock, Mockito nullpointerexception при вызове super() JDialog

Я получаю исключение NullPointerException при попытке unit test некоторых методов в объекте JDialog. Я должен инициализировать макетную версию родителя диалога, а также другой класс, который будет использоваться (в дополнение к вызову статического метода. Код выглядит следующим образом:

@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 );
  }
...
}

Код, который вызывается для построения диалога, находится здесь:

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

когда вызывается суперструктор, я в конечном итоге получаю NullPointerError в 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);
      }
    }
  }
}

Я знаю, что смешиваю статику и свинг-ги в ядовитом вихре, но у меня нет выбора. Мне была дана инструкция, чтобы собрать некоторые модульные тесты с существующим кодом. Я понятия не имею, что происходит не так.

Спасибо

Ответ 1

Выглядит сложно! По существу вам придется найти все методы, вызываемые в controlFrame как часть конструктора, а затем посыпать некоторые вызовы

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

Если это выглядит сложной задачей, как насчет того, чтобы создать стандартную реализацию IControlFrame, которую вы создаете как часть вашего тестового setUp(), и использовать эту установку макета.

У меня была аналогичная проблема некоторое время назад, когда я пытался прослушивать unit test a spring JMS. Правильно или неправильно, я получил рабочее решение, создав свою собственную реализацию по умолчанию DefaultMessageListenerContainer, которая давала мне похожие проблемы тому, что вы описываете. Мое решение включало расширение реальной реализации с помощью моей собственной тестовой версии, которая выглядела так:

/**
 * 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;
    }
}

В моем примере я смог запустить мои тесты, передав значение null для проблемного метода createConnection(). Возможно, тот же подход может помочь вам.

Ответ 2

ownedWIndowList transient в классе java.awt.Window. Является ли ваш экземпляр JDialog сериализованным? Если это так, вам может понадобиться использовать метод readObject(java.io.ObjectStream) из интерфейса Serializable для повторной инициализации ownedWIndowList

Ответ 3

Я не знаю, как выглядит ваш IControlFrame, но передача mocked Frame в super() не работает. Мне пришлось создать экземпляр моей версии:

private class EmptyControlFrame extends JFrame implements IControlFrame {

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

    // return null for any other overrides from IControlFrame
}

Затем в вашем setUp():

controlFrame = new EmptyControlFrame();