Тестируемый дизайн - PullRequest
       28

Тестируемый дизайн

1 голос
/ 03 февраля 2010

У меня есть класс Java, в котором есть статический член, созданный с помощью Facade (Singleton).

Class A implements InterfaceA {

 private static DataStore db = DataStoreFacade.getInstance("BDB"); //singleton instance

  public void save(final String key, final String val) {
     db.save(key,val);
  }
};

Здесь класс A используется в качестве переменной-члена для веб-службы (bean-компонент без сохранения состояния).

Я не могу проверить этот код с помощью EasyMock, потому что нет способа переопределить экземпляр DataStore.

Есть два варианта.

  1. Иметь конструктор, берущий экземпляр DataStore, который будет иметь значение переменной-члена db. Проблема в том, что я не хочу, чтобы класс веб-сервиса знал, какой экземпляр хранилища данных был создан.

  2. Предоставить дополнительный защищенный метод Set для переопределения объекта db. Это то, что я использовал, когда я создаю объект Easy Mock из DataStore и переопределяю переменную-член. Это правильный дизайн.

Каковы другие возможности?

Ответы [ 4 ]

0 голосов
/ 05 июля 2010

Почему бы не сделать член БД защищенным, а в вашем тестовом проекте наследовать его и переопределить этот член:

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
        }
    }
}

Он все еще скрыт от потребителей кода / библиотеки, тестовый объект не загромождаетсярабочий код и его поведение будут протестированы так, как если бы это была рабочая версия.

Однако следует помнить, что наличие статического члена для вашего объекта базы данных может вызвать проблемы в ваших тестах, если он не очищается должным образом после каждоготест. *

  • Я знаю, что вы, вероятно, уже знаете это, но я говорю это для полноты.
0 голосов
/ 04 февраля 2010

Вы правы, что плохо для тестируемости.Используйте внедрение зависимостей и не используйте статические переменные:


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);
  //...

}

0 голосов
/ 05 июля 2010

Ну, оригинальный код уже уже проверяем. Вот тестовый модуль для него, используя 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 также может быть осмеян.

0 голосов
/ 03 февраля 2010

Используйте шаблон Supersede Instance ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...