mockito: как отключить метод?

#java #testing #mockito #spy

#java #тестирование #mockito #шпион

Вопрос:

У меня есть класс JUnit с разными методами для выполнения разных тестов.

Я использую Mockito для создания шпиона в реальном экземпляре, а затем переопределяю некоторый метод, который не имеет отношения к фактическому тесту, который я выполняю.

Есть ли способ, просто ради очистки после меня на случай, если некоторые другие тесты, которые выполняются после моих тестов, также используют те же экземпляры и могут выполнить издевательский метод, который они не просили издеваться, отменить издевательство над методом?

допустим, у меня есть шпионский объект с именем ‘wareHouseSpy’

допустим, я переопределил метод ISOMETHINGMISSING :

 doReturn(false).when(wareHouseSpy).isSomethingMissing()
  

Каков будет правильный способ отменить переопределение и вернуть работу шпиона в нормальное состояние, т. е. выполнить следующий вызов isSomethingMissing для запуска реального метода?

что-то вроде

 doReturn(Mockito.RETURN_REAL_METHOD).when(wareHouseSpy).isSomethingSpy()
  

или, может быть

 Mockito.unmock(wareHouseSpy)
  

Кто знает? Я ничего не смог найти в этой области

Спасибо!

Ассаф

Комментарии:

1. «Я использую Mockito для создания шпиона в реальном экземпляре, а затем переопределяю некоторый метод, который не имеет отношения к фактическому тесту, который я выполняю». Я не понимаю, тогда зачем вы издеваетесь над ним, если он вам не нужен?

2. Является ли хранилище в вашем примере одноэлементным или что-то в этом роде? Относятся ли эти «другие тесты» к тому же классу или вы говорите о совершенно другом наборе тестов?

Ответ №1:

Я думаю

 Mockito.reset(wareHouseSpy)
  

сделал бы это.

Комментарии:

1. Это приведет к сбросу всех издеваемых методов. Я думаю, что OP хотел сбросить только один метод (по крайней мере, это то, что я пришел сюда искать :))

2. Ну, я хочу сбросить метод, а затем повторно заглушить этот метод новым значением. Но все равно сохраните verify(..., times(1)) для этого заглушку метода.

Ответ №2:

Допустим, большинство ваших тестов используют заглушенный ответ. Тогда у вас был бы метод setUp (), который выглядит следующим образом:

 @Before
public void setUp() {
  wareHouseSpy = spy(realWarehouse);
  doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
  

Теперь предположим, что вы хотите отменить заглушенный ответ и использовать реальную реализацию в одном тесте:

 @Test
public void isSomethingMissing_useRealImplementation() {
  // Setup
  when(wareHouseSpy.isSomethingMissing()).thenCallRealMethod();

  // Test - Uses real implementation
  boolean result = wareHouseSpy.isSomethingMissing();
}
  

Комментарии:

1. .thenCallRealMethod() помог мне сбросить индивидуальный издевательский метод.

2. @Rupesh справился с задачей.

Ответ №3:

Это зависит от того, проводите ли вы тестирование с помощью TestNG или JUnit.

  • JUnit создает новый экземпляр самого себя для каждого метода тестирования. В принципе, вам не нужно беспокоиться о сбросе mocks.
  • С помощью TestNG вам нужно сбросить макет (ы) с помощью Mockito.reset(mockA, mockB, ...) либо в @BeforeMethod , либо в @AfterMethod

Комментарии:

1. Не правда о JUnit, создающем новый экземпляр для каждого метода. У меня есть один метод, который нарушает работу другого метода, даже несмотря на то, что ВСЕ операции редактирования выполняются для каждого метода.

2. @AgilePro В 2011 году был только JUnit 4, и в его FAQ упоминается » Он выполняет каждый тест в отдельном экземпляре тестового класса «. Другие писали на ту же тему: Жизненный цикл тестового класса . И это также используется по умолчанию в JUnit 5 , см. Жизненный цикл экземпляра теста : » … для выполнения изолированно … JUnit создает новый экземпляр каждого тестового класса перед выполнением каждого тестового метода «.

Ответ №4:

«Обычный» способ заключается в повторном создании экземпляров в вашем методе «setUp». Однако, если у вас есть реальный объект, создание которого по какой-либо причине обходится дорого, вы могли бы сделать что-то вроде этого:

 public class MyTests {

  private static MyBigWarehouse realWarehouse = new MyBigWarehouse();
  private MyBigWarehouse warehouseSpy;

  @Before
  public void setUp() {
    warehouseSpy = spy(realWarehouse); // same real object - brand new spy!
    doReturn(false).when(wareHouseSpy).isSomethingMissing();
  }

  @Test
  ...

  @Test
  ...

  @Test
  ...
}
  

Комментарии:

1. Если вы не объявите realWarehouse как статическую переменную, она будет создаваться заново для каждого теста.

2. Вы правы. Я изменил ответ, чтобы отразить это.

Ответ №5:

Может быть, я не понимаю, но когда у вас есть реальный объект real :

 Object mySpy = spy(real);
  

Затем «отменить слежку» mySpy … просто используйте real .

Ответ №6:

Согласно документации, у нас есть

 reset(mock);
//at this point the mock forgot any interactions amp; stubbing
  

В документации указано дальнейшее

Обычно вам не нужно сбрасывать свои mocks, просто создайте новые mocks для каждого метода тестирования. Вместо #reset(), пожалуйста, рассмотрите возможность написания простых, небольших и целенаправленных методов тестирования с использованием длительных, чрезмерно заданных тестов.

Вот пример из их репозитория github, который тестирует это поведение и использует его:

 @Test
public void shouldRemoveAllInteractions() throws Exception {
        mock.simpleMethod(1);
        reset(mock);
        verifyZeroInteractions(mock);
}
  

ссылка : ResetTest.java

Ответ №7:

Обращаясь конкретно к этому фрагменту:

Есть ли способ, просто ради очистки после меня на случай, если некоторые другие тесты, которые выполняются после моих тестов, также используют те же экземпляры и могут выполнить издевательский метод, который они не просили издеваться, отменить издевательство над методом?

Если вы используете JUnit, самый простой способ сделать это — использовать @Before и @After (другие фреймворки имеют эквиваленты) и воссоздать экземпляр и шпион, чтобы ни один тест не зависел от того, что вы сделали в любом другом тесте, или на него не повлияло то, что вы сделали в любом другом тесте. Затем вы можете выполнить специфичную для теста конфигурацию spy / mock внутри каждого теста. Если по какой-то причине вы не хотите воссоздавать объект, вы можете воссоздать шпион. В любом случае, каждый раз все начинают с нового шпиона.