使用JUnit测试的不同Singleton实例

时间:2010-01-30 07:40:56

标签: junit singleton

我有一个成功通过测试的独立单身人士。但是通过一组测试,这会失败,因为一旦定义了单例,它就不允许重置实例。

关于如何解决此问题的任何想法?

7 个答案:

答案 0 :(得分:12)

我假设你的单例类中有一个私有静态字段来存储初始化的实例。

如果您不想修改代码,可以定义在每次测试后运行的拆卸方法,在此方法中,您可以通过反射将此静态字段设置为null,如here所示。

答案 1 :(得分:12)

不要使用单身人士。

具体来说,单例和全局变量之间的唯一区别是单例尝试强制执行单个实例(例如,通过使构造函数为私有)。

相反,将构造函数设为public并使用新实例编写测试。在您的实际程序中,使用getInstance()来获取规范的全局实例(或使用IOC容器)。

请记住singletons are pathological liars

如果你仍然对Singleton的想法感到满意,而不是公开构造函数,你可以添加一个公共(和静态)工厂方法,以不会意外使用的方式创建实例,例如:

public static MyClass TEST_CreateInstance() {
  return new MyClass();
}

答案 2 :(得分:3)

您可以添加一个方法来销毁单例,例如destroyMe();在那里你取消初始化所有东西并将单例的实例设置为null。

  public void destroyMe(){
   this.instance = null;
   //-- other stuff to turn it off.
}

我会留下同步问题;)

但是为什么你需要为每个测试重新初始化你的单例?它不应该基于单身人士的概念而有所不同。

答案 3 :(得分:2)

我强烈建议远离Singletons作为设计模式,并使用Singleton作为范围(依赖注入)。这只会让你的问题消失。

但是假设你被困在Singletons的世界里,那么根据你是在测试Singleton还是依赖,你有一些选择。

如果您正在测试依赖项,那么您可以使用PowerMockJMockIt来模拟单身人士。有关如何解决此问题的说明,请参阅我的previous post有关模拟Runtime.getRuntime的信息。

如果您正在测试Singleton,那么您需要放松构造规则,或者给Singleton一个“重置”方法。

答案 4 :(得分:2)

Spring为这个特殊的用例提供了DirtiesContext注释,你需要为每个测试用例提供单例bean的新实例。它基本上为每个应用了这个注释的testcase / testclass创建一个新的应用程序上下文。

答案 5 :(得分:1)

一般要小心单身人士,通常他们是邪恶的,糟糕的设计,往往代表大的令人讨厌的全局变量(这对维护不利)。

首先你可以做到以下测试:


static setInstance(...){ //package visibility or in difficult cases you have to use public
  instance = ...;
}

如上所述,这更像是一种解决方法。所以得到第一个测试的地方,然后重构离开单身模式。

答案 6 :(得分:0)

单例实例需要通过测试本身传递给SUT - 这样就可以为每个测试创建单例(和销毁)。采用IoC和模拟框架(如Mockito)会使这种方法变得微不足道。