使用PowerMock测试ConnectionFactory时触发NullPointerException问题咨询
看起来你踩了一个很常见的PowerMock测试坑——不是构造方法模拟失败,而是被测试类的字段没初始化导致的NPE。让我帮你拆解问题并给出解决方案:
问题根源分析
你看到的NullPointerException并不是因为InetSocketAddress的构造没被成功模拟,而是ConnectionFactory里的proxyHost和proxyPort字段都是null。当执行new InetSocketAddress(proxyHost, proxyPort)时,把null的proxyHost传给了InetSocketAddress的构造方法,这会直接触发空指针异常——哪怕你用PowerMock拦截了构造方法,参数传递时的null已经先一步导致错误了。
具体解决方案
方案1:给ConnectionFactory的字段初始化(推荐)
因为proxyHost和proxyPort是私有字段,有两种优雅的赋值方式:
方式A:添加Setter方法(符合OOP设计)
在ConnectionFactory类里添加字段的Setter:
public void setProxyHost(String proxyHost) { this.proxyHost = proxyHost; } public void setProxyPort(Integer proxyPort) { this.proxyPort = proxyPort; }
然后在测试的setUp方法里调用Setter赋值:
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); // 初始化proxyHost和proxyPort connectionFactory.setProxyHost("test-proxy-host"); connectionFactory.setProxyPort(1080); PowerMockito.mockStatic(Proxy.class); PowerMockito.whenNew(InetSocketAddress.class).withArguments(Mockito.anyString(), Mockito.anyInt()).thenReturn(inetSocketAddress); PowerMockito.whenNew(Proxy.class).withArguments(Proxy.Type.SOCKS, Mockito.any(InetSocketAddress.class)).thenReturn(proxy); }
方式B:用反射直接赋值(无需修改原类)
如果不想改动ConnectionFactory的代码,可以用反射工具(比如Spring的ReflectionTestUtils)直接设置私有字段:
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); // 反射设置私有字段 ReflectionTestUtils.setField(connectionFactory, "proxyHost", "test-proxy-host"); ReflectionTestUtils.setField(connectionFactory, "proxyPort", 1080); PowerMockito.mockStatic(Proxy.class); PowerMockito.whenNew(InetSocketAddress.class).withArguments(Mockito.anyString(), Mockito.anyInt()).thenReturn(inetSocketAddress); PowerMockito.whenNew(Proxy.class).withArguments(Proxy.Type.SOCKS, Mockito.any(InetSocketAddress.class)).thenReturn(proxy); }
额外配置检查
你的@PrepareForTest配置是正确的——因为要拦截ConnectionFactory里的构造方法调用,必须把ConnectionFactory加入@PrepareForTest列表,这一步你已经做到了,后续如果还有构造拦截问题,可以再核对这一点。
测试方法优化(可选)
目前你的测试只是调用了方法,没有验证任何行为,建议添加验证逻辑确保代码按预期执行:
@Test public void testInitializeProxy() throws Exception { // 模拟URL和返回的HttpURLConnection URL mockUrl = Mockito.mock(URL.class); HttpURLConnection mockConn = Mockito.mock(HttpURLConnection.class); Mockito.when(mockUrl.openConnection(proxy)).thenReturn(mockConn); // 执行测试方法 HttpURLConnection result = connectionFactory.getHttpURLConnection(mockUrl); // 验证构造方法和方法调用 PowerMockito.verifyNew(InetSocketAddress.class).withArguments("test-proxy-host", 1080); PowerMockito.verifyNew(Proxy.class).withArguments(Proxy.Type.SOCKS, inetSocketAddress); Mockito.verify(mockUrl).openConnection(proxy); Assert.assertEquals(mockConn, result); }
内容的提问来源于stack exchange,提问作者Sethu raman

