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

使用junit测试的不同单例实例

  •  22
  • kal  · 技术社区  · 15 年前

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

    有什么办法吗?

    7 回复  |  直到 13 年前
        1
  •  11
  •   orip    15 年前

    不要用单子。

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

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

    记住这一点 singletons are pathological liars .

    如果您仍然对singleton的想法很满意,那么您可以添加一个public(和static)工厂方法来创建实例,而不是将构造函数公开,这样就不会意外地使用,例如:

    public static MyClass TEST_CreateInstance() {
      return new MyClass();
    }
    
        2
  •  11
  •   Community CDub    8 年前

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

    如果不想修改代码,可以定义一个在每次测试之后运行的拆卸方法,在这个方法中,可以通过反射将这个静态字段设置为空,如图所示 here .

        3
  •  3
  •   mmmmmm    13 年前

    您可以添加一个方法来销毁singleton,例如destroyme();在这里,您取消初始化所有内容并将singleton的实例设置为空。

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

    不过,我会留下同步问题;)

    但为什么每次测试都需要重新初始化singleton?基于单重态的概念,它不应该有所不同。

        4
  •  2
  •   Community CDub    8 年前

    强烈推荐 从单例转换为设计模式,并使用单例作为作用域(依赖注入)。这只会让你的问题消失。

    但是假设你被困在单例的世界里,那么你有几个选择,这取决于你是在测试单例还是依赖项。

    如果您正在测试依赖项,则可以使用 PowerMock JMockIt . 看到我 previous post 关于mocking runtime.getruntime了解有关如何执行此操作的说明。

    如果要测试singleton,则需要放松构造规则,或者给singleton一个“reset”方法。

        5
  •  2
  •   Andy Dufresne    14 年前

    弹簧提供 DirtiesContext 此特定用例的注释,其中您需要为每个测试用例创建新的单例bean实例。它基本上为每个应用了此注释的testcase/testclass创建一个新的应用程序上下文。

        6
  •  1
  •   manuel aldana    15 年前

    通常要注意单例,通常它们是邪恶的、糟糕的设计,并且往往代表大的、讨厌的全局变量(这不利于维护)。

    仍然要先进行测试,您可以:

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

    如前所述,这是一个解决办法。所以,先做测试,然后重构出单例模式。

        7
  •  0
  •   topchef    15 年前

    singleton实例需要通过测试本身传递给sut,这样就可以为每个测试创建singleton(并销毁)。采用ioc和mocking框架,就像mockito一样,会使这种方法变得微不足道。