практически возможно сделать хороший TDD (или BDD) без использования какой-либо DI-фреймворк в Java? - PullRequest
2 голосов
/ 16 сентября 2010

IMO Одной из основных характеристик хорошего TDD является: тестирование вашего класса (или фактически единицы) в изоляции.

Когда вы делаете это, вы можете фактически тестировать одиночное поведение в каждом тесте -только одна проверка выпадет для одной вашей проблемы.

Для этого вы должны сначала убедиться, что в вашем классе нет статических ссылок (включая конструкторы AKA new ключевое слово).

inТеоретически легко не использовать какую-либо инфраструктуру внедрения зависимостей и тестировать свои классы в полной изоляции, для этого вам нужно внедрить все зависимости в конструкторе и создать классы фабрики, которые будут вызывать ключевое слово new.

Iнашел, что это теоретическое МО слишком сложно на практике.

Я что-то упустил в процессе?

РЕДАКТИРОВАТЬ : Я думаю, что все мы должны стремиться к одному провалу для одного изменения кода.он никогда не будет идеальным, но он приблизит ваш код к нему, люди забывают, что тестовый код также является обслуживаемым кодом, спецификация тестируемых изменений кода .

Если вы не нацеливаетесь тудав итоге вы удалите тесты, что является плохим решением

Ответы [ 3 ]

10 голосов
/ 16 сентября 2010

Я не думаю, что вам нужны DI-фреймворки для модульного тестирования - TDD был за годы до того, как DI стал модой. А в случае кода, который не использует саму явную структуру DI, зачем использовать это для модульных тестов?

Конечно, DI-фреймворки могут в некоторой степени упростить задачу. OTOH они делают это, помещая сложность в другом месте. Я предпочитаю проводить автономные модульные тесты, и до сих пор я почти всегда обходился без инфраструктуры DI. Это часто требует рефакторинга моего тестового кода, а иногда даже дублирования кода, но я могу с этим смириться. И, как заметил @kostja, фреймворк для насмешек тоже очень помогает.

Очень важен и дизайн для тестируемости - если класс сам по себе сложно тестировать, лучше его реорганизовать, чем пытаться облегчить боль с помощью DI-фреймворка.

Обратите внимание, что все это требует большой практики, а также изменения мышления и мышления. Все это требует времени и терпения ... чем больше вы не отставаете, тем лучше становитесь: -)

вы можете фактически протестировать одиночное поведение в каждом тесте - только один тест может быть выполнен для одной проблемы, с которой вы столкнулись.

Я думаю, что ваш вывод здесь неверен. Даже если вы тестируете одну вещь в каждом тесте, вы можете нарушить множество тестов с помощью одного изменения кода. Обновление: Каждый тест должен проверять единственный путь выполнения в тестируемом коде. Однако эти пути выполнения редко бывают независимыми - как правило, есть общие разделы пути во всех, кроме самых простых методов. Любое изменение может нарушить несколько тестов.

1 голос
/ 16 сентября 2010

DI должен уменьшить прямые зависимости, фактически упрощая макетирование и модульное тестирование.Может быть, вам не хватает макета?этот пост может прояснить ситуацию.

0 голосов
/ 24 ноября 2010

Конечно, возможно . И легко.Например, допустим, вы хотите протестировать следующий метод, который вызывает статические методы для класса Database (фасад статической персистентности) и непосредственно создает экземпляр SimpleEmail (из электронной почты Apache Commons):

public void doBusinessOperationXyz(EntityX data) throws EmailException
{
   List<EntityX> items = 
      Database.find("select x from EntityX x where x.xyz=?", data.getXyz());

   BigDecimal total = ...compute/obtain the value...
   data.setTotal(total);

   Database.persist(data);

   Email email = new SimpleEmail();
   email.setSubject("Notification about processing of ...");
   email.addTo(data.getCustomerEmail());
   email.setMsg("...some notification message...");
   email.send();
}

Этот метод может быть протестирован в отрыве от зависимостей Database и Email с помощью следующего модульного теста с использованием JMockit :

@Test
public void doBusinessOperationXyz() throws Exception
{
   final EntityX data = new EntityX(5, "abc", "5453-1");
   final List<EntityX> items = new ArrayList();
   items.add(new EntityX(1, "AX5", "someone@somewhere.com"));

   new Expectations()
   {
      @Mocked final Database unused = null;
      @NonStrict SimpleEmail email;

      {
         Database.find(withSubstring("select"), (Object[]) <em>any</em>); <em>result</em> = items;
         Database.persist(data);

         email.send(); <em>times</em> = 1;
      }
   };

   new MyBusinessService().doBusinessOperationXyz(data);
}

Как правило, необходимо ввестификтивные объекты для зависимостей Database и Email, что приводит к более сложному решению.Посмеиваясь над статическими методами и конструкторами, мы можем вместо этого сохранить простой, естественный и элегантный дизайн.

...