代码之家  ›  专栏  ›  技术社区  ›  uckelman

JUnit能模拟OutOfMemoryErrors吗?

  •  2
  • uckelman  · 技术社区  · 14 年前

    我有一个方法试图调用内存中的图像转换器,如果失败,则尝试在磁盘上进行图像转换。(内存中的图像转换器将尝试分配图像的第二个副本,因此如果原始图像非常大,我们可能没有足够的内存来存储它。)

    public BufferedImage convert(BufferedImage img, int type) {
      try {
        return memory_converter.convert(type);
      }
      catch (OutOfMemoryError e) {
        // This is ok, we just don't have enough free heap for the conversion.
      }
    
      // Try converting on disk instead.
      return file_converter.convert(img, type);
    }
    

    我想为JUnit编写单元测试,测试每个代码路径,但是如果运行JUnit时堆太少,无法强制 OutOfMemoryError OutOfMemory错误 在JUnit内部?

    我突然想到我可以做一个 BufferedImage 这会导致 OutOfMemory错误 第一次调用由内存转换器调用的方法,但随后在后续调用中表现正常。不过,这看起来像是个黑客。

    4 回复  |  直到 14 年前
        1
  •  6
  •   dty    14 年前

    您应该模拟您的转换器,而不是使用真正的转换器。

    一旦你这样做了,你只需要让你的模拟库在 convert()

    例如,对于JMock,您可以执行以下操作:

    allowing(mockConverter).convert(with(any(int.class)));
    will(throwException(new OutOfMemoryError()));
    
        2
  •  3
  •   Bert F    14 年前

    注入存根或模拟 memory_converter convert() OutOfMemryError .

    模拟框架通常非常强大,应该允许您指定这种行为。例如,JMock:

    http://www.jmock.org/returning.html

    在连续调用时返回不同的值

    有两种方法可以在不同的调用上返回不同的值。首先是定义多个期望,并从每个期望返回不同的值:

    oneOf (anObject).doSomething(); will(returnValue(10));
    oneOf (anObject).doSomething(); will(returnValue(20));
    oneOf (anObject).doSomething(); will(returnValue(30));
    

        3
  •  2
  •   Aaron McIver    14 年前

    我突然想到我可以 生成BufferedImage的假子类 第一次 然后在随后的

    你走的路是对的。模拟对象正是这些类型的东西的好处所在。您并不真正关心OutOfMemory错误是否合法,您只需要确保抛出/捕获它并执行另一条路径。把它拿出来,你就可以走了。

        4
  •  -2
  •   Horcrux7    14 年前

    OutOfMemoryError的处理和测试非常困难。你不能用模拟来测试它。根据发生OutOfMemoryError异常的位置,效果可能会非常不同。问题是OutOfMemoryError不能传递给调用代码。

    因为OutOfMemoryError可以在应用程序中的任何其他线程上产生致命错误,所以您应该防止它。我认为一个更好的解决方案是计算空闲内存。所需的内存大小,并在异常发生之前调用磁盘上的转换。