You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用PowerMockito测试HttpURLConnection POST请求时遇参数异常

Fixing the IllegalArgumentException in PowerMockito Mock for HttpURLConnection POST Test

Alright, let's break down why you're hitting that IllegalArgumentException and fix it step by step:

What's Causing the Issue?

The error java.lang.IllegalArgumentException: type null is not compatible with address null comes from two key problems:

  1. Missing PowerMockito Configuration: You're trying to mock constructors of JDK classes like URL, Proxy, and InetSocketAddress, but haven't set up PowerMockito properly to allow this. Without the right annotations, your whenNew calls won't override real constructor logic, leading to unexpected null values.
  2. Unmocked Proxy Methods: Even if you successfully mock the Proxy object, its default mock behavior returns null for methods like getType() and address(). When URL.openConnection(proxy) runs, the JDK's internal logic checks if the proxy's type and address are valid (non-null), triggering the exception.

Step-by-Step Fix

1. Add Required PowerMockito Annotations

First, your test class needs these annotations to enable mocking of JDK class constructors and control test execution:

@RunWith(PowerMockRunner.class)
@PrepareForTest({HttpClient.class, URL.class, Proxy.class, InetSocketAddress.class})
public class HttpClientTest {
    // Your test code will go here
}
  • @RunWith(PowerMockRunner.class): Tells JUnit to use PowerMock's custom test runner.
  • @PrepareForTest: Lists all classes where you need to mock constructors or static methods (your HttpClient class plus the JDK classes you're mocking).

2. Mock Proxy's Critical Validation Methods

Add these lines after creating your mock Proxy to ensure it returns valid values for the JDK's checks:

// Mock Proxy's type and address to avoid null validation failures
PowerMockito.when(proxy.getType()).thenReturn(Proxy.Type.HTTP);
PowerMockito.when(proxy.address()).thenReturn(inetAddr);

3. Fix the makeRequest Method's Return Value

Your test expects a String response, but the current makeRequest method is void. Update it to return the collected response content:

public String makeRequest(String empid, JsonObject request) {
    JsonObject variables = request.getJsonObject("variables");
    variables.put("requested_for", empid);
    request.put("variables", variables);
    StringBuffer response = new StringBuffer();
    
    try {
        String url = "Some_valid_url";
        URL obj = new URL(url);
        String proxyURL = "abc.xyz.com";
        int port = 80;
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyURL, port));
        HttpURLConnection con = (HttpURLConnection) obj.openConnection(proxy);
        
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/json");
        System.setProperty("com.sun.net.ssl.checkRevocation", "false"); // Disable SSL revocation check
        con.setDoOutput(true);
        
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        String requestBody = request.toString();
        wr.writeBytes(requestBody);
        wr.flush();
        wr.close();
        
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
    } catch (Exception e) {
        System.out.println(e);
    }
    // Return the assembled response string
    return response.toString();
}

4. Updated Test Code

Here's the full corrected test with all fixes applied, plus optional assertions to verify behavior:

public class HttpClientTest {
    private HttpClient impl;

    @Before
    public void setUp() {
        impl = new HttpClient();
    }

    @Test
    public void httpClientTest() {
        try {
            URL obj = PowerMockito.mock(URL.class);
            Proxy proxy = PowerMockito.mock(Proxy.class);
            InetSocketAddress inetAddr = PowerMockito.mock(InetSocketAddress.class);
            HttpURLConnection mockConn = PowerMockito.mock(HttpURLConnection.class);
            BufferedReader mockReader = PowerMockito.mock(BufferedReader.class);

            // Mock constructor calls to return our mocked objects
            PowerMockito.whenNew(InetSocketAddress.class).withArguments(anyString(), anyInt()).thenReturn(inetAddr);
            PowerMockito.whenNew(URL.class).withArguments(any(String.class)).thenReturn(obj);
            PowerMockito.whenNew(Proxy.class).withArguments(Proxy.Type.HTTP, inetAddr).thenReturn(proxy);

            // Mock Proxy methods to pass JDK validation
            PowerMockito.when(proxy.getType()).thenReturn(Proxy.Type.HTTP);
            PowerMockito.when(proxy.address()).thenReturn(inetAddr);

            // Mock URL openConnection to return our mock HttpURLConnection
            PowerMockito.when(obj.openConnection(proxy)).thenReturn(mockConn);

            // Mock input stream to return a sample success response
            PowerMockito.when(mockConn.getInputStream()).thenReturn(new ByteArrayInputStream("{\"status\":\"success\"}".getBytes()));
            PowerMockito.when(mockReader.readLine()).thenReturn("{\"status\":\"success\"}", null);

            // Prepare test request object
            JsonObject req = new JsonObject();
            req.add("variables", new JsonObject()); // Initialize to avoid NPE

            // Execute the test
            String response = impl.makeRequest("abc", req);
            System.out.println(response);

            // Optional: Verify the response is correct
            Assert.assertEquals("{\"status\":\"success\"}", response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Key Takeaways

  • Never skip @RunWith(PowerMockRunner.class) and @PrepareForTest when mocking JDK class constructors or static methods with PowerMockito.
  • When mocking JDK objects like Proxy, always mock methods used for internal validation (like getType() and address()) to avoid null-related exceptions.
  • Ensure your test and target method have consistent return types to avoid confusion and enable meaningful assertions.

内容的提问来源于stack exchange,提问作者ammy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:20:07