Різниця між @Mock, @MockBean та Mockito.mock ()


147

Під час створення тестів та знущань із залежностей, яка різниця між цими трьома підходами?

  1. @MockBean:

    @MockBean
    MyService myservice;
  2. @Mock:

    @Mock
    MyService myservice;
  3. Mockito.mock ()

    MyService myservice = Mockito.mock(MyService.class);

Відповіді:


199

Звичайна бібліотека Мокіто

import org.mockito.Mock;
...
@Mock
MyService myservice;

і

import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);

походять з бібліотеки Mockito і є функціонально рівнозначними.
Вони дозволяють знущатися над класом чи інтерфейсом та записувати та перевіряти поведінку на ньому.

Спосіб використання анотації коротший, настільки кращий і часто бажаний.


Зауважте, що для активації анотацій Mockito під час виконання тестових викликів необхідно викликати MockitoAnnotations.initMocks(this)статичний метод.
Щоб уникнути побічного ефекту між тестами, рекомендується робити це перед кожним виконанням тесту:

@Before 
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

Інший спосіб включення анотацій Mockito - це анотування тестового класу @RunWith, вказавши те, MockitoJUnitRunnerщо робить це завдання, а також інші корисні речі:

@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}

Бібліотека весняного завантаження, що обгортає бібліотеку Mockito

Це дійсно клас весняного завантаження :

import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;

Клас входить до spring-boot-testбібліотеки.

Це дозволяє додавати Mockito макети навесні ApplicationContext.
Якщо bean, сумісний із оголошеним класом, існує в контексті, він замінює його макетом.
Якщо це не так, це додає макет у контексті як боб.

Довідник Javadoc:

Анотація, яку можна використовувати для додавання макетів до Spring ApplicationContext.

...

Якщо будь-який існуючий один боб одного типу, визначений у контексті, буде замінений макетом, якщо не визначений існуючий боб, буде доданий новий.


Коли використовується класичний / простий Mockito та коли використовується @MockBeanвід Spring Boot?

Експериментальні випробування призначені для тестування компонента у відриві від інших компонентів, а також тестування блоків - це якомога швидше з точки зору часу виконання, оскільки ці тести можуть виконуватися щодня десятки разів на машинах розробника.

Отже, ось проста інструкція:

Коли ви пишете тест, який не потребує ніяких залежностей від контейнера Spring Boot, класичний / звичайний Mockito - це наступний шлях: це швидко і сприяє ізоляції тестованого компонента.
Якщо для вашого тесту потрібно покластись на контейнер Spring Boot, і ви хочете також додати або знущатися над однією з бобів контейнера: @MockBeanвід Spring Boot це шлях.


Типове використання весняного завантаження @MockBean

Поки ми пишемо тестовий клас з анотацією @WebMvcTest(веб-тестовий фрагмент).

Документація Spring Boot дуже добре підсумовує:

Часто @WebMvcTestбуде обмежено одним контролером і використовуватиметься в поєднанні з @MockBeanдля забезпечення макетних реалізацій для необхідних співробітників.

Ось приклад:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(FooController.class)
public class FooControllerTest {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private FooService fooServiceMock;

    @Test
    public void testExample() throws Exception {
         Foo mockedFoo = new Foo("one", "two");

         Mockito.when(fooServiceMock.get(1))
                .thenReturn(mockedFoo);

         mvc.perform(get("foos/1")
            .accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("one two"));
    }

}

4
Чи за допомогою @MockBean створіть копію квасолі та введуть її в ApplicationContext? Чи знущається боб усі свої методи як недійсні? Якщо всі методи недійсні, чи можу я заглушити їх, як я можу це зробити, використовуючи @Mock?
Дуг

6
Як було пояснено, використання @MockBeanбуде замінювати боб у контексті програми, якщо боб, що оголошує той самий тип, уже визначений у вашій конфігурації Spring. А ін'єкція виконується в класі, де ви заявляєте, @MockBean.механізми DI працюють таким чином: ви реєструєте об'єкт у контексті DI, а потім можете вводити об'єкт, на який посилається у контексті Spring, у конкретний клас. Ви не вводите об'єкт у контекст DI.
davidxxx

13

Зрештою, це легко пояснити. Якщо ви просто заглянете в javadocs анотацій, ви побачите різні:

@Mock: ( org.mockito.Mock)

Позначте поле як макет.

  • Дозволяє створювати макети зі скороченням.
  • Зводить до мінімуму код створення макетів, що повторюються
  • Робить тестовий клас більш читабельним.
  • Полегшує читання помилку підтвердження, оскільки назва поля використовується для ідентифікації макета.

@MockBean: ( org.springframework.boot.test.mock.mockito.MockBean)

Анотація, яку можна використовувати для додавання макетів до Spring ApplicationContext. Може використовуватися як анотація на рівні класу, або на полях у будь-яких @Configurationкласах, або в тестових класах, що є @RunWithSpringRunner.

Макети можуть бути зареєстровані за типом або за ім'ям бобів. Будь-який існуючий один боб одного типу, визначений у контексті, буде замінений макетом, якщо не визначений існуючий боб, буде доданий новий.

Коли @MockBeanвін використовується в полі, а також буде зареєстрований у контексті програми, макет також буде введений у поле.

Mockito.mock ()

Його справедливе представлення @Mock.


5
Не забуваймо, що @Mock вимагає виклику MockitoRunner або initMocks вручну.
Флоріан Шает

4
Це єдина відмінність між @MockBeanі @Mockщо один буде вводити знущаються в Spring ApplicationContextі інший не буде?
Даг

3
@Doug Ви це добре підсумували, але потрібно пам’ятати, що MockBean є частиною весняного завантаження
ком’юнітор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.