Mockito тестировние void метода
а что вы пытаетесь протестировать? опишите словами ваш тест.
2 янв 2017 в 7:45
Я хочу проверить, что метод delete получив id выполнит удаление и вернет true.
2 янв 2017 в 11:25
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вот мой вариант.
public void delete(Long id) < // так делать плохо // добавлено по просьбе вопрошающего try < // проверку на существование и пр. должен делать MessageRepository messageRepository.delete(id); >catch(EmptyResultDataAccessException ex) < throw new DataNotFoundException("Data with not found."); >>
private static final Long интерфейс, а не реализация private MessageRepository messageRepository; @Test public void detele_delegateToRepository() throws Exception < // подготовка messageRepository = mock(MessageRepository.class); // не знаю как у вас класс называется - будем считать Subject Subject subject = new Subject(messageRepository); // действие subject.delete(ID); // проверка verify(messageRepository).delete(ID); >@Test(expected = DataNotFoundException.class) public void detele_throwsException() throws Exception < // подготовка messageRepository = mock(MessageRepository.class); // не знаю как у вас класс называется - будем считать Subject Subject subject = new Subject(messageRepository); when(messageRepository.delete(ID)).thenThrow(new EmptyResultDataAccessException()); // действие subject.delete(ID); >
Это все что вам надо тестировать. Остальные тесты должны быть у класса который реализует MessageRepository.
Как протестировать void метод с помощью java
Для тестирования void методов в Java используются различные техники, такие как написание юнит-тестов с использованием фреймворков для тестирования, например JUnit или TestNG , или написание тестовых классов вручную.
Для тестирования void метода мы можем создать экземпляр тестируемого класса, вызвать его метод и затем проверить, что он выполнился правильно. Например, если есть метод void incrementCounter() , который должен увеличивать значение счетчика на единицу, мы можем написать следующий тестовый метод:
import org.junit.Test; import static org.junit.Assert.assertEquals; @Test public void testIncrementCounter() // Arrange MyClass myClass = new MyClass(); int initialCounterValue = myClass.getCounter(); // Act myClass.incrementCounter(); // Assert int newCounterValue = myClass.getCounter(); assertEquals(initialCounterValue + 1, newCounterValue); >
В этом тестовом методе мы создаем экземпляр класса MyClass , получаем начальное значение счетчика, вызываем метод incrementCounter() , а затем проверяем, что значение счетчика увеличилось на единицу.
Мокирование void методов с помощью Mockito
Один из самых распространенных вопросов, возникающих при работе с Mockito, — как замокировать методы с возвращаемым типом void. Это может быть требуемо во многих ситуациях, особенно при использовании паттерна Observer, где методы часто не возвращают значения.
Допустим, есть класс World , который содержит метод addListener , добавляющий слушателей, и метод doAction , который выполняет некоторое действие и обновляет состояние системы.
public class World < List<Listener> listeners; void addListener(Listener item) < listeners.add(item); >void doAction(Action goal,Object obj) < setState("i received"); goal.doAction(obj); setState("i finished"); >private String state; //setter getter state >
И есть тестовый класс WorldTest , который пытается замокировать World и добавить себя в качестве слушателя.
public class WorldTest implements Listener < @Test public void word< World w= mock(World.class); w.addListener(this); . . >>
Здесь возникает проблема: система не реагирует на добавление мока.
В Mockito есть инструменты для решения этой проблемы. Вместо того чтобы вызывать метод addListener напрямую, можно использовать конструкцию doNothing().when() .
doNothing().when(mockedObject).voidMethod();
В данном случае, это будет выглядеть так:
doNothing().when(w).addListener(this);
После этого, можно вызвать addListener без проблем. Вызов doNothing().when() гарантирует, что ничего не будет сделано при вызове метода. Это идеально подходит для методов с void возвратом, так как они, по определению, ничего не возвращают.
Важно помнить, что Mockito не может замокировать методы, которые являются финальными или статическими. В таких ситуациях следует пересмотреть дизайн кода или использовать другой инструмент для мокирования.
В заключение, хотелось бы отметить, что использование Mockito может значительно упростить процесс тестирования и сделать его более предсказуемым.
Популярные сценарии работы с Mockito
И еще один важный момент – мокирование и верификация статических методов. “А что в этом такого?”, – спросишь ты. Да, статические, но ведь методы же. И будете неправы.
Помни, с чего мы начали изучение мок-объектов? С того, что эти объекты искусственно создаются через класс DynamicProxy . А статические методы ни к каким объектам не привязаны и перехватить вызовы к ним через DynamicProxy нельзя . Вот и все.
Но создатели Mockito и тут смогли извернуться – написали свой загрузчик классов и с его помощью смогли подменять классы на лету. Большая и сложная работа, но они все-таки смогли это сделать.
Понадобится добавить дополнительную библиотеку в pom.xml :
org.mockito mockito-inline 4.2.0 test
Вот как нужно работать, если вам нужно мокировать статический метод.
1 Создаем специальный мок-объект класса:
MockedStaticИмяКласса>управляющийОбъект = Mockito.mockStatic(ИмяКласса.class);
2 Добавляем к этому объекту правила работы:
К этому объекту правила нужно цеплять другими способами.
управляющийОбъект.when(ИмяКласса::имяМетода).thenReturn(результат);
3 Обязательно заворачиваем использование этого объекта в try-with-resources , чтобы объект сразу удалился и Mockito могло очистить связанные с ним правила.
@Test void givenStaticMethodWithNoArgs () < try (MockedStatic< StaticUtils> utilities = Mockito.mockStatic( StaticUtils.class)) < //добавляем правило utilities.when(StaticUtils::name).thenReturn("Привет"); //проверяем, что правило работает assertEquals("Привет", StaticUtils.name()); > >
Не так красиво, как с аннотациями @Mock и @Spy , зато очень практично. Было очень тяжело писать тесты, когда нельзя было замокать простой статический метод, который использовался внутри тестируемых методов.