Mock Static Methods with Mockito

Published
In the pursuit of clean object-oriented code, the need to mock static methods may suggest design flaws or code smells, prompting consideration for refactoring. Nevertheless, there are situations where mocking static methods remains crucial despite refactoring efforts.
Over the years, different approaches have been adopted for mocking static methods. Let's delve into these approaches in detail.

Utilizing PowerMockito with Mockito Prior to v3.4.0

Prior to Mockito v3.4.0, PowerMockito was utilized to mock static methods and was compatible with JUnit 4 which you can integrate by adding the following dependency to the pom.xml file.
pom.xml
<properties> <powermock.version>2.0.2</powermock.version> </properties> <dependencies> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> </dependencies>
In AEM projects, there's often a need to interact with third-party APIs. Let's use Apache HttpClient, commonly used for invoking external APIs, as an example to write unit test using PowerMockito.
RestClientServieimpl.java
public HttpClient getHttpClient(int... timeout) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); int connectionTimeout = Arrays.stream(timeout).findFirst() .orElse(CONNECTION_TIMEOUT); RequestConfig config = RequestConfig.custom() .setConnectTimeout(connectionTimeout * 1000) .setConnectionRequestTimeout(connectionTimeout * 1000) .setSocketTimeout(connectionTimeout * 1000).build(); httpClientBuilder.setDefaultRequestConfig(config); return httpClientBuilder.build(); }
RestClientServieimplTest.java
@RunWith(PowerMockRunner.class) @PrepareForTest({ HttpClientBuilder.class }) public class RestClientServieimplTest { @Mock CloseableHttpClient httpClient; @Mock HttpClientBuilder httpClientBuilder; @InjectMocks RestClientServieImpl restClient; @Before public void setup() { MockitoAnnotations.initMocks(this); PowerMockito.mockStatic(HttpClientBuilder.class); Mockito.when(HttpClientBuilder.create()).thenReturn(httpClientBuilder); Mockito.when(httpClientBuilder.build()).thenReturn(httpClient); } @Test public void getHttpClientTest() { Assert.assertNotNull(restClient); HttpClient httpClient = restClient.getHttpClient(); Assert.assertNotNull(httpClient); } }