I have the below method which depends only on private members. This is a class that is run by a 3rd party library. I only need to specify the name of the class and it will create an instance of the class and run it. I don't want to pass these private variables through constructor as it doesn't make any sense. But to verify whether the methods that should be called inside this method are called, I need those members.
private IClientMqtt iClient;
private IConnectOpts iConnectOpts;
private MqttClient client;
private MqttConnectOptions connOpts;
private String clientId;
private String url;
private String topic;
Logger logger;
private ILogProvider logProvider;
@Override
public void init() {
Injector injector = Guice.createInjector(new GuiceModule());
logProvider = injector.getInstance(ILogProvider.class);
logger = logProvider.getLogger();
iClient = injector.getInstance(IClientMqtt.class);
try {
client = iClient.createClient(this.url, this.clientId);
iConnectOpts = injector.getInstance(IConnectOpts.class);
connOpts = iConnectOpts.createConnectOpts();
connOpts.setCleanSession(true);
try {
client.setCallback(this);
client.connect();
client.subscribe(topic);
} catch (MqttSecurityException e) {
logger.error("Mqtt Security Exception occurred while initializing the MQTTAppender");
} catch (MqttException e) {
logger.error("MqttException occurred while initializing the MQTT Appender");
}
} catch (ServiceSDKException ex) {
logger.error("Service SDK Exception caused when creating MqttClient for initializing of Mqtt Appender",ex);
}
}
I tried with Whitebox.setInternal state by passing a mock object.
Whitebox.setInternalState(mqttAppenderSpy, "iClient",mockMqttClient);
But I am getting the below exception.
java.lang.RuntimeException: Unable to set internal state on a private field. Please report to mockito mailing list.
at org.mockito.internal.util.reflection.Whitebox.setInternalState(Whitebox.java:29)
at com.kohls.kube.service.sdk.logging.MQTTAppenderTest.should_create_a_mqtt_client_instance_when_init_method_is_called(MQTTAppenderTest.java:33)
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:483)
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.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
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.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
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:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.IllegalArgumentException: Can not set org.eclipse.paho.client.mqttv3.MqttClient field com.kohls.kube.service.sdk.logging.appender.mqtt.MQTTAppender.client to com.kohls.kube.service.sdk.logging.appender.mqtt.messaging.IClientMqtt$$EnhancerByMockitoWithCGLIB$$24b26828
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
at java.lang.reflect.Field.set(Field.java:758)
at org.mockito.internal.util.reflection.Whitebox.setInternalState(Whitebox.java:27)
... 28 more
Below is the test I tried to write.
@Test
public void should_create_a_mqtt_client_instance_when_init_method_is_called() throws ServiceSDKException {
doCallRealMethod().when(mqttAppenderSpy).init();
IClientMqtt clientMqttMock = mock(IClientMqtt.class);
MqttClient mockMqttClient = mock(MqttClient.class);
when(clientMqttMock.createClient(any(String.class),any(String.class)));
Whitebox.setInternalState(mqttAppenderSpy, "client", clientMqttMock);
Whitebox.setInternalState(mqttAppenderSpy, "iClient",mockMqttClient);
mqttAppenderSpy.init();
IClientMqtt clientMqtt = (IClientMqtt) Whitebox.getInternalState(mqttAppenderSpy, "iclient");
verify(clientMqtt.createClient(any(String.class), any(String.class)));
}
Am I doing something wrong here? Is this the only way to test this method is there a better way I could do this? Please advice.
Aucun commentaire:
Enregistrer un commentaire