Mockito.mock () vs @Mock vs @MockBean

Mockito.mock() vs @Mock vs @MockBean

1. Vue d'ensemble

Dans ce rapide didacticiel, nous examinerons trois façons différentes de créer des objets simulés et en quoi ils diffèrent les uns des autres - avec Mockito et avec la prise en charge de la simulation Spring.

Lectures complémentaires:

Mockito ArgumentMatchers

Découvrez comment utiliser ArgumentMatcher et en quoi il diffère de ArgumentCaptor.

Read more

Exception moqueuse Lancer à l'aide de Mockito

Apprenez à configurer un appel de méthode pour générer une exception dans Mockito.

Read more

2. Mockito.mock()

La méthodeMockito.mock() nous permet de créer un objet factice d'une classe ou d'une interface.

Ensuite, nous pouvons utiliser le modèle pour stub renvoyer les valeurs de ses méthodes et vérifier si elles ont été appelées.

Regardons un exemple:

@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockedValueReturned() {
    UserRepository localMockRepository = Mockito.mock(UserRepository.class);
    Mockito.when(localMockRepository.count()).thenReturn(111L);

    long userCount = localMockRepository.count();

    Assert.assertEquals(111L, userCount);
    Mockito.verify(localMockRepository).count();
}

Cette méthode n’a pas besoin d’autre chose à faire avant de pouvoir être utilisée. Nous pouvons l'utiliser pour créer des champs de classe fictifs, ainsi que des mocs locaux dans une méthode.

3. Annotation@Mock de Mockito

Cette annotation est un raccourci pour la méthodeMockito.mock(). De plus, nous ne devrions l'utiliser que dans une classe de test. Contrairement à la méthodemock(), nous devons activer les annotations Mockito pour utiliser cette annotation.

Nous pouvons le faire soit en utilisant lesMockitoJUnitRunner pour exécuter le test, soit en appelant explicitement la méthodeMockitoAnnotations.initMocks().

Regardons un exemple utilisantMockitoJUnitRunner:

@RunWith(MockitoJUnitRunner.class)
public class MockAnnotationUnitTest {

    @Mock
    UserRepository mockRepository;

    @Test
    public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
        Mockito.when(mockRepository.count()).thenReturn(123L);

        long userCount = mockRepository.count();

        Assert.assertEquals(123L, userCount);
        Mockito.verify(mockRepository).count();
    }
}

En plus de rendre le code plus lisible,@Mock makes it easier to find the problem mock in case of a failure, as the name of the field appears in the failure message:

Wanted but not invoked:
mockRepository.count();
-> at org.example.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
Actually, there were zero interactions with this mock.

  at org.example.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)

En outre, lorsqu'il est utilisé avec@InjectMocks, il peut réduire considérablement la quantité de code de configuration.

4. Annotation@MockBean de Spring Boot

Nous pouvons utiliser les@MockBean pour ajouter des objets fictifs au contexte de l'application Spring. La maquette remplacera tout bean existant du même type dans le contexte de l'application.

Si aucun haricot du même type n'est défini, un nouveau sera ajouté. Cette annotation est utile dans les tests d'intégration où un bean particulier, par exemple un service externe, doit être simulé.

Pour utiliser cette annotation, nous devons utiliserSpringRunner pour exécuter le test:

@RunWith(SpringRunner.class)
public class MockBeanAnnotationIntegrationTest {

    @MockBean
    UserRepository mockRepository;

    @Autowired
    ApplicationContext context;

    @Test
    public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
        Mockito.when(mockRepository.count()).thenReturn(123L);

        UserRepository userRepoFromContext = context.getBean(UserRepository.class);
        long userCount = userRepoFromContext.count();

        Assert.assertEquals(123L, userCount);
        Mockito.verify(mockRepository).count();
    }
}

Lorsque nous utilisons l'annotation sur un champ, en plus d'être enregistrés dans le contexte de l'application, la maquette est également injectée dans le champ.

Ceci est évident dans le code ci-dessus. Ici, nous avons utilisé le smockUserRepository injecté pour stub le smethodcount _._ Nous avons ensuite utilisé le bean du contexte de l'application pour vérifier qu'il s'agit bien du bean simulé.

5. Conclusion

Dans cet article, nous avons vu en quoi les trois méthodes de création d'objets fictifs diffèrent et comment chacune d'entre elles peut être utilisée.

Le code source qui accompagne cet article est disponibleover on GitHub.