我有以下测试:
@After
public void tear_down() {
remove_test_data();
}
private void remove_test_data() {
delete_product("product1").close()
}
@Test
public void test_crud() {
Product product = product_factory("product1");
Response response = post_product(product);
assertThat(response.getStatus(), is(201));
response.close();
response = get_product(product);
assertThat(response.getStatus(), is(200));
Product gottenProduct = response.readEntity(ProductList.class);
response.close();
}
private Response get_product(Product product) {
return provider
.target()
.path(product.getName())
.request(MediaType.APPLICATION_JSON)
.get();
return response;
}
但是,如果第二个断言失败(assertThat(response.getStatus(), is(200))
),则不会为此响应调用response.close()
。这意味着我在拆解时遇到以下异常:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
at org.apache.http.util.Asserts.check(Asserts.java:34)
at org.apache.http.impl.conn.BasicClientConnectionManager.getConnection(BasicClientConnectionManager.java:160)
at org.apache.http.impl.conn.BasicClientConnectionManager$1.getConnection(BasicClientConnectionManager.java:142)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:423)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:283)
我应该怎么做以避免这个问题?
答案 0 :(得分:1)
这是一个简单的try-finally用例,例如:
try {
// do work here
} finally {
if (response != null) response.close()
}
或者,您可能需要查看Junit为测试管理提供的After
注释。这些通常用于清理操作。
至于你的上一个问题,你可以在做其他任何事情之前尝试关闭你的回复。但是,请阅读以下文档:
/**
* Close the underlying message entity input stream (if available and open)
* as well as releases any other resources associated with the response
* (e.g. {@link #bufferEntity() buffered message entity data}).
* <p>
* This operation is idempotent, i.e. it can be invoked multiple times with the
* same effect which also means that calling the {@code close()} method on an
* already closed message instance is legal and has no further effect.
* </p>
* <p>
* The {@code close()} method should be invoked on all instances that
* contain an un-consumed entity input stream to ensure the resources associated
* with the instance are properly cleaned-up and prevent potential memory leaks.
* This is typical for client-side scenarios where application layer code
* processes only the response headers and ignores the response entity.
* </p>
* <p>
* Any attempts to manipulate (read, get, buffer) a message entity on a closed response
* will result in an {@link IllegalStateException} being thrown.
* </p>
*
* @throws ProcessingException if there is an error closing the response.
* @since 2.0
*/
这意味着,如果您关闭响应,则可能会遇到不同的错误。例如,您提供的测试如下所示:
response = get_product(product);
assertThat(response.getStatus(), is(200));
Product gottenProduct = response.readEntity(ProductList.class);
response.close();
如果在阅读实体之前关闭了您的响应,则实体流将被关闭,这将为您抛出异常。
所以,我认为,如果你想在不使用JUnit注释的代码中正确关闭它,那么你应该使用try-finally
。