Issue
I have a plugin with jenkins version set to 1.580.3.And when I upgrade the jenkins version to 1.642.3<=version , it is throwing a null pointer exception.Below is the stacktrace
java.lang.NullPointerException
at hudson.model.Label.hashCode(Label.java:528)
at java.util.HashMap.hash(HashMap.java:338)
at java.util.HashMap.put(HashMap.java:611)
at java.util.HashSet.add(HashSet.java:219)
at java.util.Collections.addAll(Collections.java:5401)
at com.google.common.collect.Sets.newHashSet(Sets.java:183)
at com.ericsson.oss.axis.ATest.setUp(ATest.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.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:132)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:95)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
below is my code
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.Is.is;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jvnet.jenkins.plugins.nodelabelparameter.LabelParameterValue;
import org.mockito.Answers;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.XXXXX.JenkinsUtils;(internal)
import com.google.common.collect.Sets;
import hudson.model.AbstractBuild;
import hudson.model.Label;
import hudson.model.ParameterValue;
import hudson.model.ParametersAction;
import jenkins.model.Jenkins;
@RunWith(PowerMockRunner.class)
@PrepareForTest( JenkinsUtils.class)
public class A{
@Mock
private Label label;
@Mock
private Jenkins jenkins;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private AbstractBuild build;
@Before
public void setUp() {
PowerMockito.mockStatic(JenkinsUtils.class);
try {
doReturn(Sets.newHashSet(label)).when(jenkins).getLabels();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(NodeLabelParameterUtils.class )
public class B{
private BaselineDefinedMessageDispatcher unit;
private BuildData buildData = new BuildData();
private MyBuildDetails myBuildDetails;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private AbstractBuild build;
@Mock
private BuildLogger buildLogger;
@Mock
private Label label;
@Mock
private Computer computer;
@Mock
private PretendSlave node;
@Mock
private FreeStyleProject project;
@Mock
private Jenkins jenkins;
@Mock
private EnvironmentVariableResolver envVarsResolver;
@Before
public void setUp() throws IOException, InterruptedException, Descriptor.FormException {
unit = spy(new BaselineDefinedMessageDispatcher(null, null));
unit.setBuildLogger(mock(BuildLogger.class));
MyBuildDetails = mock(MyBuildDetails.class);
doReturn("expectedSlaveHost").when(unit).getHostNameFromSlave(any(Node.class));
doReturn(project).when(build).getProject();
doReturn(Sets.<Node>newHashSet(node)).when(label).getNodes();
doReturn(node).when(build).getBuiltOn();
doReturn(jenkins).when(unit).getJenkinsInstance();
doReturn(Sets.newHashSet(label)).when(jenkins).getLabels();
PowerMockito.mockStatic(A.class);
when(envVarsResolver.processString(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
return (String) invocationOnMock.getArguments()[0];
}
});
}
The following dependencies are being used
powermock-api-mockito - 1.6.3
mockito-core - 1.9.5
junit - 4.11
java - 1.8
jenkins.version - 1.642.3
I get the error exactly at doReturn(Sets.newHashSet(label)).when(jenkins).getLabels(); in class A. This is a maven project and when jenkins version is set to 1.580.3 mvn clean install is success but when it is version>=1.642.3 it is failing. My aim is to upgrade jenkins verison to 2.X.I went through manyworkarounds in stackoverflow but nothing worked Any help is appreciated
Solution
Edit:
Looks like my orignal answer was just incorrect.
The NPE comes from the fact that the abstract Label
class has a constructor parameter called name
. This parameter is used to calculate the hashcode of the label.
If you mock it this name
is null
and you get the NPE.
The question now is do you need to create a mock of this or can you actually use a real instance? In the exmaple below I just used one of the implementations of that class LabelAtom
. If a mock is required because you need to define some behaviour on the object that you can not get otherwise, you probably have to use a spy
.
(Tested with org.jenkins-ci.main:jenkins-core:2.85
)
import static org.mockito.Mockito.doReturn;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.common.collect.Sets;
import hudson.model.Label;
import hudson.model.labels.LabelAtom;
import jenkins.model.Jenkins;
@RunWith(PowerMockRunner.class)
public class Test {
@Mock
private Jenkins jenkins;
private Label label;
@Before
public void setUp() {
Assert.assertNotNull(jenkins);
label = new LabelAtom("someName");
// or if a mock is required
//label = Mockito.spy(new LabelAtom("someName"));
doReturn(Sets.newHashSet(label)).when(jenkins).getLabels();
}
@Test
public void test() {
}
}
Regarding the WithOrWithoutExpectedArguments
I was not able to reproduce that one.
Answered By - second