1

我有一个 java 类,它有一个使用 Facade (Singleton) 创建的静态成员。

A 类实现 InterfaceA {

 私有静态 DataStore db = DataStoreFacade.getInstance("BDB"); //单例实例

  公共无效保存(最终字符串键,最终字符串val){
     db.save(key,val);
  }
};

这里A类用作webservice(无状态bean)的成员变量。

我无法使用 EasyMock 测试此代码,因为无法覆盖 DataStore 实例。

有两种选择。

  1. 有一个构造函数采用 DataStore 的实例,该实例将设置为 db 成员变量。问题是我不希望 webservice 类知道创建了哪个数据存储实例。

  2. 提供一个额外的受保护的 Set 方法来覆盖 db 对象。这就是我在创建 DataStore 的 Easy Mock 对象并覆盖成员变量时使用的方法。设计是否正确。

其他的可能性是什么?

4

4 回答 4

0

你是对的,这对可测试性不利。使用依赖注入,不要使用静态变量:


public class A implements InterfaceA {

  private DataStore db;

  public A(DataStore db) {
    this.db = db;
  }

...

}

注入或构建使用依赖注入框架(例如spring)或自己在引导工厂代码中的某处构建对象。

生产代码:


new A(DataStoreFacade.getInstance("...");

测试代码:


public void test_xxx(){
  DataStore db = EasyMock.createMock(DataStore.class);
  //... do some expectations and replay(db)
  InterfaceA a=new A(db);
  //...

}

于 2010-02-03T22:15:31.160 回答
0

好吧,原始代码已经可以测试了。这是一个使用JMockit的单元测试:

@Test
public void testSave(final DataStore mockDb)
{
    final String key = "aKey";
    final String value = "aValue";

    new A().save(aKey, aValue);

    new Verifications()
    {{
        mockDb.save(key, value);
    }};
}

如果需要,DataStoreFacade也可以模拟该课程。

于 2010-07-05T15:10:26.183 回答
0

为什么不让 db 成员受保护,并在您的测试项目中继承它并覆盖该成员:

project 
{
    Class A
    {
        protected static db = ...
        public void Save(...) { ... }
    }
}

test_project
{
    Class B : A
    {
        protected override static db = ... (create test db)
    }

    Class testB
    {
        public A a;

        public void Setup()
        {
            this.a = new B();
        }

        public void TearDown()
        {
            // delete a
        }

        public void TestSaveKey()
        {
            // test a
        }
    }
}

它仍然对代码/库的使用者隐藏,测试对象不会弄乱生产代码,并且行为将像生产版本一样进行测试。

但请注意,如果在每次测试后没有正确清理 db 对象的静态成员,可能会给您的测试带来麻烦。*

  • 我知道您可能已经知道这一点,但我是为了完整起见。
于 2010-07-05T15:24:45.320 回答
0

使用取代实例模式...

http://goodcoffeegoodcode.blogspot.com/2010/01/supercede-instance-pattern.html

于 2010-02-03T18:59:08.460 回答