如何用Mockito模拟返回非空HttpsURLConnection的静态方法?
解决Mockito/PowerMockito模拟静态HTTP连接返回null的问题
针对你遇到的静态方法模拟返回null导致空指针的问题,下面给出两种可行的解决方案,分别基于Mockito-inline(Mockito 3.4+支持静态方法模拟)和PowerMockito:
一、使用Mockito-inline实现模拟
1. 依赖配置(Maven示例)
确保引入正确版本的Mockito-inline和JUnit 5依赖:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency>
2. 测试用例实现
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; import java.net.HttpURLConnection; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) public class YourToolClassTest { @Mock private HttpURLConnection mockConnection; // 模拟的连接对象 @Test void testYourToolMethod() throws Exception { // 初始化sslURLDetails Map<String, String> sslURLDetails = new LinkedHashMap<>(); sslURLDetails.put("MPOWER_SSL_RTCS_URL1", "https://"); sslURLDetails.put("SSL_KEY_STORE_FILENAME", "C:/Users/Desktop/certs/XYZ/report.jks"); sslURLDetails.put("SSL_TRUST_STORE_FILE_NAME", "C:/Users/Desktop/certs/XYZ/report.jks"); sslURLDetails.put("SSL_USER_PASSCODE", ""); sslURLDetails.put("SSL_KEY_STORE_TYPE", "JKS"); sslURLDetails.put("SSL_URL_ENABLED", "true"); // 模拟HttpsURLServiceUtil的静态方法 try (MockedStatic<HttpsURLServiceUtil> mockedStatic = mockStatic(HttpsURLServiceUtil.class)) { mockedStatic.when(() -> HttpsURLServiceUtil.openHttpURLConnection(sslURLDetails)) .thenReturn(mockConnection); // 如果工具类中用到URL.openConnection(),同步模拟 URL mockUrl = new URL("https://example.com"); try (MockedStatic<URL> urlMockedStatic = mockStatic(URL.class)) { urlMockedStatic.when(() -> new URL(any(String.class))).thenReturn(mockUrl); when(mockUrl.openConnection()).thenReturn(mockConnection); // 调用你的工具类方法 YourToolClass.yourMethod(sslURLDetails); // 可添加验证逻辑,比如确认setRequestMethod被调用 // verify(mockConnection).setRequestMethod("POST"); } } } }
二、使用PowerMockito实现模拟
1. 依赖配置(Maven示例)
<dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito2</artifactId> <version>2.0.9</version> <scope>test</scope> </dependency>
2. 测试用例实现
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.net.HttpURLConnection; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest({HttpsURLServiceUtil.class, URL.class}) // 指定要模拟的静态类 public class YourToolClassTest { @Mock private HttpURLConnection mockConnection; @Test void testYourToolMethod() throws Exception { // 初始化sslURLDetails Map<String, String> sslURLDetails = new LinkedHashMap<>(); sslURLDetails.put("MPOWER_SSL_RTCS_URL1", "https://"); sslURLDetails.put("SSL_KEY_STORE_FILENAME", "C:/Users/Desktop/certs/XYZ/report.jks"); sslURLDetails.put("SSL_TRUST_STORE_FILE_NAME", "C:/Users/Desktop/certs/XYZ/report.jks"); sslURLDetails.put("SSL_USER_PASSCODE", ""); sslURLDetails.put("SSL_KEY_STORE_TYPE", "JKS"); sslURLDetails.put("SSL_URL_ENABLED", "true"); // 模拟HttpsURLServiceUtil静态方法 PowerMockito.mockStatic(HttpsURLServiceUtil.class); when(HttpsURLServiceUtil.openHttpURLConnection(sslURLDetails)) .thenReturn(mockConnection); // 模拟URL类的构造和openConnection方法 URL mockUrl = PowerMockito.mock(URL.class); PowerMockito.whenNew(URL.class).withArguments(any(String.class)).thenReturn(mockUrl); when(mockUrl.openConnection()).thenReturn(mockConnection); // 调用工具类方法 YourToolClass.yourMethod(sslURLDetails); // 验证逻辑示例 // PowerMockito.verifyStatic(HttpsURLServiceUtil.class); // HttpsURLServiceUtil.openHttpURLConnection(sslURLDetails); } }
关键注意事项
- 参数匹配要准确:如果需要匹配特定的
sslURLDetails,用eq(sslURLDetails);不关心具体参数时,用any(Map.class)即可。 - Mockito-inline必须用
MockedStatic的try-with-resources语法,确保静态模拟的生命周期正确管理。 - PowerMockito必须通过
@PrepareForTest注解指定所有需要模拟的静态类,否则静态方法模拟会失效。
内容的提问来源于stack exchange,提问作者ASR
相关产品推荐
相关产品推荐

