I want to mock the static method being invoked from the constructor of my class.
My class:
package com.javaeasily.demos.junit;
import java.util.ArrayList;
public class MyClass {
private int number;
private static final ArrayList<String> ACTIVE_SERVICES_POST_RECONFIGURE = new ArrayList<>();
// Only allow construction if number is greater than one
MyClass() {
ACTIVE_SERVICES_POST_RECONFIGURE.add("my-node-" NodeUtils.getMyNode());
}
public void reconfigureNode() {
if (ACTIVE_SERVICES_POST_RECONFIGURE.isEmpty()) {
return;
}
}
}
Here NodeUtils.getMyNode() is the static method being invoked from the constructor of the class.
NodeUtils.java Class:
package com.javaeasily.demos.junit;
import org.apache.maven.surefire.shade.booter.org.apache.commons.lang3.StringUtils;
public class NodeUtils {
private static final String HOSTNAME_PREFIX = "my-node-";
public static String hostnameToNode(String hostname) {
if (!hostname.startsWith(HOSTNAME_PREFIX)) {
throw new IllegalArgumentException(hostname " is not recognized hostname");
}
return StringUtils.removeStart(hostname, HOSTNAME_PREFIX);
}
public static String getHostname() {
return System.getenv("HOSTNAME");
}
public static String getMyNode() {
return hostnameToNode(getHostname());
}
}
MyClassTest.java
package com.javaeasily.demos.junit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class MyClassTest {
private MyClass myclass;
@BeforeEach
public void SetUp() {
myclass = new MyClass();
}
@Test
public void testReconfigureNode() {
myclass.reconfigureNode();
}
}
When I try & run the only test case I get the following error:
java.lang.NullPointerException
at com.javaeasily.demos.junit.NodeUtils.hostnameToNode(NodeUtils.java:8)
at com.javaeasily.demos.junit.NodeUtils.getMyNode(NodeUtils.java:19)
at com.javaeasily.demos.junit.MyClass.<init>(MyClass.java:12)
at com.javaeasily.demos.junit.MyClassTest.SetUp(MyClassTest.java:11)
I am not sure how do we mock the method to avoid this error?
Since I am new to Java I am not able to catch this. Any help here is appreciated.
CodePudding user response:
So to answer your question how to mock a static method: mockito allows this since version 3.8.0. You can find a tutorial here at Baeldung
This allows generating a statically mocked Object for a concrete context, which you can create within a try block. For your case this would look like the following.
Fixed Unit Test
package com.javaeasily.demos.junit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class MyClassTest {
private MyClass myclass;
@BeforeEach
public void SetUp() {
try (MockedStatic<NodeUtils> nodeUtilsMockedStatic = Mockito.mockStatic(NodeUtils.class)) {
nodeUtilsMockedStatic.when(NodeUtils::getMyNode).thenReturn("foo");
myclass = new MyClass();
}
}
@Test
public void testReconfigureNode() {
myclass.reconfigureNode();
}
}
Mockito dependency
You need mockito with at least version 3.8.0 in your project.
With maven add:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
With gradle add:
testImplementation group: 'org.mockito', name: 'mockito-inline', version: '3.8.0'