При создании тестов и издевательских зависимостей в чем разница между этими тремя подходами?
-
@MockBean:
@MockBean MyService myservice;
-
@Mock:
@Mock MyService myservice;
-
Mockito.mock()
MyService myservice = Mockito.mock(MyService.class);
При создании тестов и издевательских зависимостей в чем разница между этими тремя подходами?
@MockBean:
@MockBean
MyService myservice;
@Mock:
@Mock
MyService myservice;
Mockito.mock()
MyService myservice = Mockito.mock(MyService.class);
Обычная библиотека Mockito
import org.mockito.Mock;
...
@Mock
MyService myservice;
а также
import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);
происходят из библиотеки Mockito и функционально эквивалентны.
Они позволяют издеваться над классом или интерфейсом, а также записывать и проверять поведение на нем.
Способ использования аннотации короче, поэтому предпочтительнее и часто предпочтительнее.
Обратите внимание, что для включения аннотаций Mockito во время тестовых исполнений необходимо MockitoAnnotations.initMocks(this)
статический метод MockitoAnnotations.initMocks(this)
.
Чтобы избежать побочного эффекта между испытаниями, рекомендуется выполнить его перед каждым выполнением теста:
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
Еще один способ включить аннотации Mockito - аннотировать тестовый класс с помощью @RunWith
, указав MockitoJUnitRunner
который выполняет эту задачу, а также другие полезные вещи:
@RunWith(org.mockito.runners.MockitoJUnitRunner.class)
public MyClassTest{...}
Библиотека загрузочной библиотеки Spring Boot Mockito
Это действительно класс Spring Boot:
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
Класс включен в библиотеку spring-boot-test
.
Это позволяет добавлять Mockito mocks в Spring ApplicationContext
.
Если в контексте существует компонент, совместимый с объявленным классом, он заменяет его макетом.
Если это не так, он добавляет макет в контексте в виде компонента.
Ссылка на Javadoc:
Аннотации, которые можно использовать для добавления mocks в Spring ApplicationContext.
...
Если какой-либо существующий один компонент одного и того же типа, определенный в контексте, будет заменен макетом, если никакой существующий bean-компонент не определен, будет добавлен новый.
Когда вы используете классический/простой Mockito и когда используете @MockBean
из Spring Boot?
Модульные тесты предназначены для тестирования компонента в изоляции от других компонентов, а также для тестирования модулей также требуется: как можно быстрее с точки зрения времени выполнения, поскольку эти тесты могут выполняться каждый день десятками раз на машинах-разработчиках.
Следовательно, вот простое руководство:
Когда вы пишете тест, который не требует каких-либо зависимостей от контейнера Spring Boot, классический/простой Mockito - это способ следовать: он быстрый и способствует изоляции тестируемого компонента.
Если ваш тест должен опираться на контейнер Spring Boot, и вы хотите также добавить или издеваться над одним из контейнеров: @MockBean
из Spring Boot - это путь.
Типичное использование 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"));
}
}
В конце его легко объяснить. Если вы просто посмотрите на javadocs аннотаций, вы увидите различия:
@Mock: (org.mockito.Mock
)
Отметьте поле как макет.
- Позволяет создавать сокращенные макеты.
- Минимизирует повторяющийся код создания фальсификации.
- Делает тестовый класс более удобочитаемым.
- Делает ошибку проверки легче читать, потому что имя поля используется для идентификации макета.
@MockBean: (org.springframework.boot.test.mock.mockito.MockBean
)
Аннотации, которые можно использовать для добавления mocks в Spring ApplicationContext. Может использоваться в качестве аннотации уровня класса или по полям в классах
@Configuration
или тестовых классах, которые являются@RunWith
.Mocks может быть зарегистрирован по типу или по имени bean-компонента. Любой существующий один компонент одного и того же типа, определенный в контексте, будет заменен макетом, если никакой существующий bean-компонент не определен, новый будет добавлен.
Когда
@MockBean
используется в поле, а также регистрируется в контексте приложения, макет также будет введен в поле.
Mockito.mock()
Его просто представление
@Mock
.
Единственное отличие, которое я вижу, заключается в том, что @Mock создает для смоделированного объекта значение по умолчанию этого класса, в то время как смоделированному объекту, созданному с помощью @MockBean по умолчанию, присваивается значение Null. Чтобы явно использовать то же самое в тестовом классе, нам нужно еще раз создать его экземпляр.