Java 最小化单元测试期间的对象保留

Java 最小化单元测试期间的对象保留,java,unit-testing,memory-leaks,Java,Unit Testing,Memory Leaks,我有一个关于内存管理/内存泄漏的问题需要澄清 设立: 我正在测试一些servlet代码,这些代码接受HttpServletRequest,HttpResponse对象引用HttpServletRequest#getParameter(字符串)、HttpServletRequest#getHeader(字符串)和HttpServletRequest#getAttribute(字符串) 我正在为servlet代码编写单元测试。为了允许测试,我为HttpServletRequest和HttpServl

我有一个关于内存管理/内存泄漏的问题需要澄清

设立:

我正在测试一些servlet代码,这些代码接受HttpServletRequest,HttpResponse对象引用HttpServletRequest#getParameter(字符串)、HttpServletRequest#getHeader(字符串)和HttpServletRequest#getAttribute(字符串)

我正在为servlet代码编写单元测试。为了允许测试,我为HttpServletRequest和HttpServletResponse创建了允许测试的存根。示例代码如下所示:

public final class HttpServletRequestStub implements HttpServletRequest {

  private Map<String, String> parameterMap = new HashMap<String, String>();
  private Map<String, String> headerMap = new HashMap<String, String>();
  private Map<String, String> attributeMap = new HashMap<String, String>();

  public void setParameter(String param, String value) {
    this.parameterMap.put(param, value);
  }
  public void setHeader(String param, String value) {
    this.headerMap.put(param, value);
  }
  @Override
  public void setAttribute(String param, String value) {
    this.attributeMap.put(param, value);
  }
  public void flush() {
     this.parameterMap.clear();
     this.headerMap.clear();
     this.attributeMap.clear();
  }

  @Override
  public String getParameter (String parameter) {
    return this.parameterMap.get(parameter);
  }
  @Override
  public String getHeader(String parameter) {
    return this.headerMap.get(parameter);
  }
  @Override
  public String getAttribute(String attribute) {
    return this.attributeMap.get(attribute);
  }

   .... Other stubbed methods




}
我的问题是关于内存管理。是否有必要在测试执行后刷新假头、请求和属性映射内容,或者在我的分解方法(用@after注释)中取消对请求、响应对象的引用后是否会自动执行?。我是否必须在我的下拉方法中显式调用flush方法来清除内存引用?我想我可能需要使用弱HashMap而不是HashMap为存根映射设置弱引用,但我不知道这是否是正确的选择。我通读了这篇文章,但仍然不清楚。任何援助都是有益的

谢谢


Kartik

对象的解引用应该足够了。Java垃圾收集器会删除所有无法访问的对象,即没有任何引用可以帮助访问它们。如果您怀疑您的对象是否真的消失了,您可以使用任何可用的java探查器


顺便说一句,我可以建议您使用一种可用的模拟对象实现,而不是自己实现塞族请求存根之类的东西吗?例如,参见EasyMock。还有一个建议。有一些JUnit扩展已经实现了所有与web相关的存根。见阿帕奇仙人掌

对象的解引用应该足够了。Java垃圾收集器会删除所有无法访问的对象,即没有任何引用可以帮助访问它们。如果您怀疑您的对象是否真的消失了,您可以使用任何可用的java探查器


顺便说一句,我可以建议您使用一种可用的模拟对象实现,而不是自己实现塞族请求存根之类的东西吗?例如,参见EasyMock。还有一个建议。有一些JUnit扩展已经实现了所有与web相关的存根。见阿帕奇仙人掌

由于单元测试的独立性,JUnit为每个测试方法创建新的MyTest对象


也就是说,
testFoo()
testBar()
在不同的MyTest实例中被调用。您的代码足以解决内存问题,在这种情况下甚至不需要
tearDown()
。由于以前的MyTest实例可供GC使用,所以如果没有其他引用它们,则其成员也可供GC使用。

由于单元测试的独立性,JUnit为每个测试方法创建新的MyTest对象

也就是说,
testFoo()
testBar()
在不同的MyTest实例中被调用。您的代码足以解决内存问题,在这种情况下甚至不需要
tearDown()
。由于以前的MyTest实例可供GC使用,所以它的成员也可供GC使用,如果没有其他引用的话

public class MyTest {
   private MyServlet servlet;

   private HttpServletRequest request;

   private HttpServletResponse response;

   @Before
   public void setUp() throws Exception {
      request = new HttpServletRequestStub();
      response = new HttpServletResponseStub(); // Not in the sample code but implemented.
      servlet = new MyServlet();
   }

   @After
   public void tearDown() throws Exception {
      request = null;
      response = null;
      servlet = null;
   }

  @Test
  public void testFoo() throws Exception {
     request.setParameter("foo", "bar");
     request.setAttribute("attrib", "attrib");
     request.setHeader("header", "header");
     servlet.service(request, response);
  }


}