正如@Brice所说,PermGen的问题来自于您对模拟对象的广泛使用。Powermock和Mockito都会创建一个新类,该类位于被模拟类和测试代码之间。该类在运行时创建并加载到PermGen中,并且(几乎)永远不会被回收。因此,您在PermGen空间上遇到了问题。
回答您的问题:
1)共享静态变量被认为是一种代码异味。在某些情况下是必要的,但它会在测试之间引入依赖关系。测试A需要在测试B之前运行。
2)使用静态方法返回模拟对象并不是真正的代码异味,这是一种常用的模式。如果您真的无法增加permgen空间,则有多种选择:
使用模拟池,在将模拟对象放回池中时使用
PowerMock#reset()
。这将减少您正在进行的创建数量。
其次,您说您的类是final的。如果可以更改,则可以在测试中使用匿名类。这再次减少了使用的permgen空间量:
Foo myMockObject = new Foo() {
public int getBar() { throw new Exception(); }
}
第三,你可以引入一个接口(在Eclipse中使用重构 -> 提取接口),然后扩展一个什么也不做的空类。然后,在你的类中,你可以像上面那样做。我经常使用这种技术,因为我发现它更容易阅读:
public interface Foo {
public int getBar();
}
public class MockFoo implements Foo {
public int getBar() { return 0; }
}
接下来在类中:
Foo myMockObject = new MockFoo() {
public int getBar() { throw new Exception(); }
}
我必须承认我并不是特别喜欢嘲笑,只有在必要的时候才会使用它,我倾向于使用匿名类扩展类或创建一个真正的MockXXX类。有关这个观点的更多信息,请参见Uncle Bob的《Mocking Mocking and Testing Outcomes》
顺便说一句,在maven surefire中,您总是可以使用forkMode=always,这将为每个测试类分叉jvm。但这并不能解决您的Eclipse问题。