【问题标题】:Java Junit test HTTP POST requestJava Junit 测试 HTTP POST 请求
【发布时间】:2012-05-17 12:02:34
【问题描述】:

我需要在不改变方法本身的情况下测试以下方法。 该方法向服务器发出 POST 方法。但是我需要做一个独立于服务器的测试用例。

我在将其重定向到本地文件之前测试了类似的方法。 但为此,我将协议作为文件,主机名作为 localhost,端口作为 -1。

我的问题是这个方法做了一个帖子并转换为 HttpURLConnection 和 wr = new DataOutputStream(conn.getOutputStream());无法通过 http 处理本地 txt 文件。

//构造函数

public HTTPConnector(String usr, String pwd, String protocol,
            String hostname, int port) {
        this.usr = usr;
        this.pwd = pwd;
        this.protocol = protocol;
        this.hostname = hostname;
        this.port = port;

        // connect();
    }

//我需要测试的方法

public String doPost(String reference, String data) throws IOException {
        URL url = null;
        HttpURLConnection conn = null;
        BufferedReader rd = null;
        DataOutputStream wr = null;
        InputStream is = null;
        String line = null;
        StringBuffer response = null;

        url = new URL(protocol, hostname, port, reference);
        conn = (HttpURLConnection) url.openConnection();

        conn.setRequestMethod("POST");

        conn.setRequestProperty("Authorization", "Basic dGVzdDphc2Rm");
        conn.setRequestProperty("Content-Type", "application/xml");

        conn.setUseCaches(false);
        conn.setDoInput(true);
        conn.setDoOutput(true);

        // Send response
        wr = new DataOutputStream(conn.getOutputStream());
        wr.writeBytes(data);
        wr.flush();
        wr.close();

        // Get response
        is = conn.getInputStream();
        rd = new BufferedReader(new InputStreamReader(is));
        response = new StringBuffer();
        while ((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
        }
        rd.close();
        return response.toString();
    }

//我可以测试的方法

public String doGet(String reference) throws IOException {
        connect();
        URL url = new URL(protocol, hostname, port, reference);
        InputStream content = (InputStream) url.getContent();

        BufferedReader xml = new BufferedReader(new InputStreamReader(content));
        return xml.readLine();
    }

【问题讨论】:

  • 你看过使用模拟对象吗?
  • 它不会去任何本地的东西,所以我发现很难重定向它。如果我能找到一种方法将其重定向到本地文件或类,那么我可以解决,但我能看到的唯一方法是制作本地服务器/线程。但这意味着我必须将我的测试定向到服务器,以便在那里获取数据,并且服务器本身需要被编程为处理请求,这比效率要高得多。

标签: java http testing post junit


【解决方案1】:

这是一个示例测试。请注意,我所做的断言仅用于演示目的,您需要适应您的需求。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ toTest.class, URL.class, HttpURLConnection.class })
public class soTest {
    /**
     * test response.
     */
    private static final String TEST_RESPONSE = "test\nresponse";

    /**
     * test data.
     */
    private static final String DATA = RandomStringUtils.randomAscii(125);

    /**
     * test port.
     */
    private static final int PORT = 8080;

    /**
     * test hosts.
     */
    private static final String HOSTNAME = "hostname";

    /**
     * test protocol.
     */
    private static final String PROTOCOL = "http";

    /**
     * test reference.
     */
    private static final String REFERENCE = "REFERENCE";

    /**
     * URL mock.
     */
    private URL url;

    /**
     * HttpURLConnection mock.
     */
    private HttpURLConnection connection;

    /**
     * Our output.
     */
    private ByteArrayOutputStream output;

    /**
     * Our input.
     */
    private ByteArrayInputStream input;

    /**
     * Instance under tests.
     */
    private toTest instance;

    @Before
    public void setUp() throws Exception
    {
        this.url = PowerMockito.mock(URL.class);
        this.connection = PowerMockito.mock(HttpURLConnection.class);

        this.output = new ByteArrayOutputStream();
        this.input = new ByteArrayInputStream(TEST_RESPONSE.getBytes());
        this.instance = new toTest(PROTOCOL, HOSTNAME, PORT);

        PowerMockito.whenNew(URL.class).withArguments(PROTOCOL, HOSTNAME, PORT, REFERENCE).thenReturn(this.url);
    }

    @Test
    public void testDoPost() throws Exception
    {
        PowerMockito.doReturn(this.connection).when(this.url).openConnection();
        PowerMockito.doReturn(this.output).when(this.connection).getOutputStream();
        PowerMockito.doReturn(this.input).when(this.connection).getInputStream();

        final String response = this.instance.doPost(REFERENCE, DATA);

        PowerMockito.verifyNew(URL.class);
        new URL(PROTOCOL, HOSTNAME, PORT, REFERENCE);

        // Mockito.verify(this.url).openConnection(); // cannot be verified (mockito limitation) 
        Mockito.verify(this.connection).getOutputStream();
        Mockito.verify(this.connection).setRequestMethod("POST");
        Mockito.verify(this.connection).setRequestProperty("Authorization", "Basic dGVzdDphc2Rm");
        Mockito.verify(this.connection).setRequestProperty("Content-Type", "application/xml");
        Mockito.verify(this.connection).setUseCaches(false);
        Mockito.verify(this.connection).setDoInput(true);
        Mockito.verify(this.connection).setDoOutput(true);
        Mockito.verify(this.connection).getInputStream();

        assertArrayEquals(DATA.getBytes(), this.output.toByteArray());
        assertEquals(TEST_RESPONSE.replaceAll("\n", "\r") + "\r", response);
    }
}


@Data
public class toTest {
    private final String protocol, hostname;

    private final  int port;

    public String doPost(String reference, String data) throws IOException
    {
        // your method, not modified
    }
}

依赖:

  • commons-lang 2.5
  • powermock-api-mockito 1.4.11
  • powermock-module-junit4 1.4.11
  • junit 4.10
  • lombok 0.11.0 测试类

【讨论】:

  • 这似乎是一个很好的解决方案,但我得到一个错误,不知道如何解决它也许你可以阐明:类型 org.powermock.modules.junit4.common.internal.impl。 AbstractCommonPowerMockRunner 无法解析。它是从所需的 .class 文件中间接引用的
  • 这个类是powermock-module-junit4提供的,奇怪。你应该检查你的类路径
【解决方案2】:

如果您没有机会重构被测方法,那么一种新颖的方法是模拟它使用的HttpUrlConnection。乍一看,这似乎很困难,因为HttpUrlConnection 没有作为参数传入。但是,您可以通过控制从url.openConnection 返回的连接来控制这一点。

这由在java.net.URL 注册的协议处理程序管理,用于您传递给构造函数的协议。诀窍是注册一个新的协议处理程序(详见Java - Registering custom URL protocol handlers)。

您的新协议处理程序应该返回一个模拟的 HttpUrlConnection,然后您可以在测试中使用它。

【讨论】:

    猜你喜欢
    • 2022-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    相关资源
    最近更新 更多