У меня есть следующий, сильно упрощенный класс:
public class MyClass
{
private MqttClient field;
public void test() throws MqttException
{
field = new MqttClient(null, null);
field.connect();
}
}
Я использую Eclipse Paho's MqttClient
класс.
Я хочу проверить метод test
с помощью UnitTest.Чтобы иметь возможность управлять экземпляром MqttClient
, я хочу смоделировать объект.Мой тестовый класс выглядит следующим образом:
public class TestMyClass
{
// Make sure we are running with the PowerMockAgent initialized
static
{
PowerMockAgent.initializeIfNeeded();
}
// Make sure we are using PowerMock
@Rule
public PowerMockRule rule = new PowerMockRule();
// Mocked MqttClient
@Mock
MqttClient field;
// MyClass-Object injected with mocks.
@InjectMocks
MyClass myClass = new MyClass();
@PrepareForTest(MyClass.class)
@Test
public void test() throws Exception
{
// Initialize our mocks from annotations
MockitoAnnotations.initMocks(this);
// Catch the "new MqttClient(null, null);"
PowerMockito.whenNew(MqttClient.class).withAnyArguments().thenReturn(field);
myClass.test();
}
}
Когда я выполняю свой тест, у меня возникает следующая ошибка:
java.lang.NullPointerException
at test.java.test.MyClass.test(MyClass.java:13)
at test.java.test.TestMyClass.test(TestMyClass.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Я могу вызвать любой метод на field
, этовсегда нулевая ссылка.Моя проблема в том, что я понятия не имею, почему это так.
Я изменил тип field
на несколько других классов, включая java.awt.point
и SerializationInstantiatorHelper
(чтобы проверить, связано ли это с MqttClient
, являющимся внешней зависимостью), а также с несколькими классами в моем проекте, вызвав соответствующий метод для этих объектов.Во всех этих случаях проблема не существовала, и тест прошел без проблем.Метод на объекте mock вызывается и ничего не делает - так, как я хочу.
Только при использовании класса MqttClient
возникает эта проблема.Или, по крайней мере, я еще не нашел другого класса, чтобы воспроизвести эту проблему.
Я, честно говоря, полностью потерян в этот момент.Что делает класс MqttClient
особенным?Почему я не могу издеваться над другими классами?Что я пропустил?
// EDIT
Я сузил проблему, создав локальную версию MqttClient
, скопировав исходный код.Честно говоря, сейчас я еще больше запутался.Класс имеет три конструктора со следующими сигнатурами:
1.)
public MqttClient( String serverURI,
String clientId) throws MqttException
2.)
public MqttClient( String serverURI,
String clientId,
MqttClientPersistence persistence) throws MqttException
3.)
public MqttClient( String serverURI,
String clientId,
MqttClientPersistence persistence,
ScheduledExecutorService executorService) throws MqttException
Если удалить один из этих трех конструкторов, все работает. Любая комбинация класса с двумя из этих трех конструкторов работает нормально. Как только все три конструктора существуют, появляется упомянутое сообщение об ошибке.Это приводит меня к предположению, что это может быть связано с PowerMockito, не найдя правильный конструктор?Если так, как этого можно избежать?