27.06.2011

Mock-тестирование mockito

Для mock-тестирования лично мне больше всего нравится mockito, актуальная версия на сегодняшний день - 1.8.5.

Посмотрим как тестировать, например, EJB stateless бин с помощью mockito.

Суть mock-тестирования в том, что мы тестируем только один, интересующий нас класс, подразумевая, что все классы, услугами которых он пользуется работают как надо.

Допустим наш stateless берет на себя работу по
 1. сбору данных со стороннего сервиса,
 2. изменение этих данных и
 3. кеширование измененного результата.

Причем сервисы сбора и кеширования уже реализованы в других EJB. Исходный код таков:

@Stateless
public class DataBean implements DataLocal {
  @EJB CacheProvider cache;
  @EJB DataGrabber grabber;

   public void doWork() {
     // 1. Получаем данные со стороннекго сервиса
     PieceOfData data = grabber.fetchData(new Date());
   
    // 2. Трансформируем данные
    TransformedData result = DataTransformer.transform(data);

    cache.put(result); // 3. Кешируем данные
  }
}

Плохо знакомый с mock-ами разработчик обычно встает перед вопросом - а как же нам протестировать работу DataBean, с mockito это очень даже просто.

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
...
@RunWith(MockitoJUnitRunner.class) // (1)
public class ResultsBeanTest {

    @Mock // (2)
    CacheProvider cache;
    @Mock
    DataGrabber grabber;
    @InjectMocks // (3)
    private DataBean bean = new DataBean();

    @Test
    public void doWorkPerfectly() {
      PieceOfData correctPieceOfData = ...; // (4)
      TransformedData correctResult = ...

       // (5)
       when(grabber.fetchData(any())).thenReturn(correctPieceOfData);

      // (6)
      bean.doWork();

      // (7)
      verify(cache).put(correctResult);
    }
}

(1) - запускать тест будем с помощью специального mockito-runner-а.
(2) - аннотируем @Mock объект, работа которого нас не интересует, считаем что он работает как надо, делаем из него mock.
(3) - создаем тестируемый объект, с помощью аннотации инжектируем в него созданные ранее mock-объекты
(4) - создаем объекты содержащие исходные данные для тестирования и объекты для сравнения результатов
(5) - задаем поведение mock-ов
(6) - вызываем тестируемый метод
(7) - проверяем положил ли тестируемый объект то что нужно в кеш.

2 comments:

Никита Кокшаров комментирует...

А Jmockit пробовали?

http://code.google.com/p/jmockit/

Андрей комментирует...

нет, просмотрю его. Чем по-вашему он примечателен?