Mockito и JUnit 5 - Использование ExtendWith

Mockito и JUnit 5 - Использование ExtendWith

1. Вступление

В этой быстрой статье мы покажемhow to integrate Mockito with the JUnit 5 extension model. Чтобы узнать больше о модели расширения JUnit 5, взгляните на этотarticle.

Во-первых, мы покажем, как создать расширение, которое автоматически создает фиктивные объекты для любого атрибута класса или параметра метода, аннотированного@Mock.

Затем мы будем использовать наше расширение Mockito в тестовом классе JUnit 5.

2. Maven Зависимости

2.1. Требуемые зависимости

Давайте добавим зависимости JUnit 5 (юпитер) иmockito к нашемуpom.xml:


    org.junit.jupiter
    junit-jupiter-engine
    5.3.1
    test


    org.mockito
    mockito-core
    2.21.0
    test

Обратите внимание, что junit-jupiter-engine - основная библиотека JUnit 5, аjunit-platform-launcher используется с плагином Maven и средством запуска IDE.

2.2. Плагин Surefire

Давайте также сконфигурируем плагин Maven Surefire для запуска наших тестовых классов с использованием новой платформы запуска JUnit:


    maven-surefire-plugin
    2.19.1
    
        
             org.junit.platform
             junit-platform-surefire-provider
             1.0.1
         
     

2.3. Зависимости совместимости JUnit 4 IDE

Чтобы наши тесты были совместимы с JUnit4 (vintage), для IDE, которые еще не поддерживают JUnit 5, давайте включим следующие зависимости:


    org.junit.platform
    junit-platform-runner
    1.2.0
    test


     org.junit.vintage
     junit-vintage-engine
     5.2.0
     test

Кроме того, мы должны рассмотреть возможность аннотирования всех наших тестовых классов с помощью@RunWith(JUnitPlatform.class)

Последние версииjunit-jupiter-engine,junit-vintage-engine,junit-platform-launcher иmockito-core можно загрузить с Maven Central.

3. Расширение Mockito

Mockito обеспечивает реализацию расширений JUnit5 в библиотеке -mockito-junit-jupiter. Мы включим эту зависимость в нашpom.xml:


    org.mockito
    mockito-junit-jupiter
    2.23.0
    test

4. Создание тестового класса

Давайте создадим наш тестовый класс и добавим к нему расширение Mockito:

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
public class UserServiceUnitTest {

    UserService userService;

... //
}

Мы можем использовать аннотацию@Mock, чтобы внедрить имитацию переменной экземпляра, которую мы можем использовать в любом месте тестового класса:

@Mock UserRepository userRepository;

Также мы можем ввести фиктивные объекты в параметры метода:

@BeforeEach
void init(@Mock SettingRepository settingRepository) {
    userService = new DefaultUserService(userRepository, settingRepository, mailClient);

    Mockito.lenient().when(settingRepository.getUserMinAge()).thenReturn(10);

    when(settingRepository.getUserNameMinLength()).thenReturn(4);

    Mockito.lenient().when(userRepository.isUsernameAlreadyExists(any(String.class))).thenReturn(false);
}

Обратите внимание на использование здесьMockito.lenient(). Mockito выдаетUnsupportedStubbingException,, когда инициализированный макет не вызывается одним из тестовых методов во время выполнения. Мы можем избежать этой строгой проверки заглушки, используя этот метод при инициализации макетов.

Мы можем даже вставить фиктивный объект в параметр метода тестирования:

@Test
void givenValidUser_whenSaveUser_thenSucceed(@Mock MailClient mailClient) {
    // Given
    user = new User("Jerry", 12);
    when(userRepository.insert(any(User.class))).then(new Answer() {
        int sequence = 1;

        @Override
        public User answer(InvocationOnMock invocation) throws Throwable {
            User user = (User) invocation.getArgument(0);
            user.setId(sequence++);
            return user;
        }
    });

    userService = new DefaultUserService(userRepository, settingRepository, mailClient);

    // When
    User insertedUser = userService.register(user);

    // Then
    verify(userRepository).insert(user);
    Assertions.assertNotNull(user.getId());
    verify(mailClient).sendUserRegistrationMail(insertedUser);
}

Обратите внимание, что макетMailClient, который мы вводим в качестве параметра теста, НЕ будет тем же экземпляром, который мы внедрили в методinit.

5. Заключение

Junit 5 предоставил хорошую модель для расширения. Мы продемонстрировали простое расширение Mockito, которое упростило нашу логику создания макетов.

Весь код, используемый в этой статье, можно найти в пакетеcom.example.junit5.mockito дляGitHub project вместе с несколькими дополнительными методами модульного тестирования.