Пользователь
19 октября 2009 в 10:27

Разработка → Глоток МоКито

JAVA*
А Вы знаете что такое mock-объект? Нет?

Что же говорит по этому поводу википедия: «В объектно-ориентированном программировании mock-объект имитирует поведение реального объекта заданным образом… ». Казалось бы зачем? Википедия продолжает: «Во время unit-тестирования mock-объекты могут симулировать поведение бизнес-объектов и бизнес-логику, что иногда необходимо из-за сложности реального поведения»


И что же дают mock-библиотеки java-разработчику? Конечно же удобство создания и использования тех самых mock-объектов!

java-source.net приводит список аж из 7 библиотек:

Я начал знакомство с mock-объектами c другой библиотеки, которой нет на java-source.net — Mockito. Я просто доверился мнению javaposse, признавших mockito библиотекой недели, а так же настроению java-блогосферы и не разочаровался. Вы тоже оцените насколько это удобно:

Внимание! Сделав глоток — остановиться невозможно.

Проверяем поведение


mock-объект будет запоминать любые вызовы его методов, чтобы после Вы могли проверить какие методы вызывал ваш тестируемый код у mock-объекта
Copy Source | Copy HTML
  1. //статически импортируем методы (для красоты и легкости кода)
  2. import static org.mockito.Mockito.*;
  3.  
  4. //вот он - mock-объект (заметьте: List.class - это интерфейс)
  5. List mockedList = mock(List.class);
  6.  
  7. //используем его
  8. mockedList.add("one");
  9. mockedList.clear();
  10.  
  11. //проверяем, были ли вызваны методы add с параметром "one" и clear
  12. verify(mockedList).add("one");
  13. verify(mockedList).clear();

А как же stub'ы?


По умолчанию все методы mock объекта возвращают default'ные значение, false для boolean, 0 для int, пустые коллекции, null для остальных объектов.
Copy Source | Copy HTML
  1. //Вы можете создавать mock для конкретного класса, не только для интерфейса
  2. LinkedList mockedList = mock(LinkedList.class);
  3.  
  4. //stub'инг
  5. when(mockedList.get(0)).thenReturn("first");
  6. when(mockedList.get(1)).thenThrow(new RuntimeException());
  7.  
  8. //получим "first"
  9. System.out.println(mockedList.get(0));
  10.  
  11. //получим RuntimeException
  12. System.out.println(mockedList.get(1));
  13.  
  14. //получим "null" ибо get(999) не был определен
  15. System.out.println(mockedList.get(999));

Проверяем точное количество вызовов


Copy Source | Copy HTML
  1. //используем mock-объект
  2. mockedList.add(«once»);
  3.  
  4. mockedList.add(«twice»);
  5. mockedList.add(«twice»);
  6.  
  7. mockedList.add(«three times»);
  8. mockedList.add(«three times»);
  9. mockedList.add(«three times»);
  10.  
  11. //по умолчанию проверка, что вызывался 1 раз ~ times(1)
  12. verify(mockedList).add(«once»);
  13. verify(mockedList, times(1)).add(«once»);
  14.  
  15. //точное число вызовов
  16. verify(mockedList, times(2)).add(«twice»);
  17. verify(mockedList, times(3)).add(«three times»);
  18.  
  19. //никогда ~ never() ~ times(0)
  20. verify(mockedList, never()).add(«never happened»);
  21.  
  22. //как минимум, как максимум
  23. verify(mockedList, atLeastOnce()).add(«three times»);
  24. verify(mockedList, atLeast(2)).add(«five times»);
  25. verify(mockedList, atMost(5)).add(«three times»);

Паразитируем на реальных объектах


Вы можете создать mock-объект, (точнее spy-объект) который будет использовать реальный объект при вызовах метода. Перегрузив лишь необходимые вам методы, так сказать частичный mock-объект.
Copy Source | Copy HTML
  1. List list = new LinkedList();
  2. List spy = spy(list);
  3.  
  4. //опционально, определяем лишь метод size()
  5. when(spy.size()).thenReturn(100);
  6.  
  7. //используем реальные методы
  8. spy.add("one");
  9. spy.add("two");
  10.  
  11. //получим "one"
  12. System.out.println(spy.get(0));
  13.  
  14. //метод size() нами переопределён - получим 100
  15. System.out.println(spy.size());
  16.  
  17. //можем проверить
  18. verify(spy).add("one");
  19. verify(spy).add("two");

А так же


  • Используем маски в аргументах переопределяемых методов
  • Переопределяем методы, возвращающие void
  • Проверяем порядок вызовов mock-объекта
  • Ищем ненужные вызовы mock-объекта
  • Аннотация Mock
  • Различные возвращаемые значения, для одних и тех же аргументов
  • остатки сладки

Дополнительная литература:

Спасибо. И да, в этом посте 58 раз упоминается слово mock
Михаил Седов @sedovmik
карма
128,4
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (10)

  • +2
    я наверное не выспался, но мне mock померещился как:
    а знаете ли вы что такео моск-обьект? :))))
    • 0
      * такое
  • 0
    Если использовать мок объекты для мониторинга за живой системой, сильно ли это повлияет на производительность? Т.е. в живой работающей системе подменять «моками» объекты, за которыми хочется понаблюдать.
    • 0
      наоборот, моками заменяют объекты за которыми НЕ хочется наблюдать.
      Например, есть сервис возвращающий погоду в заданный день — для тестов мы заменяем его моком, который будет возвращать какое-то значение, что бы проверить как работает остальное.
      • 0
        да, уже разобрался, спасибо ))
  • +3
    Эх, все эти библиотеки хороши, но лучше бы была только одна стандартизированная (как junit). А то изучишь одну, а в следующем проекте окажется, что используется совсем другая — и опять переучиваться. По этой же причине и внедрение этих библиотек не велико — каждого нового человека нужно соотвествующей библиотеке обучать.
    • +1
      Есть ещё вполне удобный, хотя может менее распостранённый testng :)
    • 0
      Если есть методичка, хотя бы в виде существующих тестов, которые используют соответствующую mocking library, то новые люди учатся использовать ее весьма быстро. Как говорится, monkey see, monkey do.
  • 0
    Как насчет https://jmockit.dev.java.net/?
  • 0
    В 1990 году фирма мелодия выпустила единственную пластинку группы "Лунный пьеро", на которой была песня Страшный Мок. Читая эту статью, я убедился, что это неправда. Моки — они совсем не страшные.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.