3 votes

Injection d'un bean autogéré en utilisant Mockito et en définissant certaines propriétés sur le mock.

Compte tenu des éléments suivants @Component classe :

@Component
public class MovieFinderImpl implements MovieFinder {

    @Autowired
    private Movie movie;

    @Override
    public List<Movie> findAll() {      
        List<Movie> movies = new ArrayList<>();
        movies.add(movie);
        return movies;
    }

}

J'essaie d'apprendre comment tester unitairement cet exemple de composant sans faire de test d'intégration (donc pas de test d'intégration). @RunWith(SpringRunner.class) y @SpringBootTest sur la classe de test).

Quand ma classe de test ressemble à ceci :

public class MovieFinderImplTest {

    @InjectMocks
    private MovieFinderImpl movieFinderImpl;

    @Mock
    public Movie movieMock;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        movieMock.setTitle("test");
        movieMock.setDirector("directorTest");
    }

    @Test
    public void testFindAll() {         
        List<Movie> movies = movieFinderImpl.findAll();
        Assert.assertNotNull(movies.get(0));

        String expectedTitle = "test";
        String actualTitle = movies.get(0).getTitle();
        Assert.assertTrue(String.format("The expected name is %s, but the actual name is %s", expectedTitle, actualTitle), expectedTitle.equals(actualTitle));

        String expectedDirector = "testDirector";
        String actualDirector = movies.get(0).getDirector();
        Assert.assertTrue(String.format("The expected name is %s, but the actual name is %s", expectedDirector, actualDirector), expectedDirector.equals(actualDirector));
    }
}

... l'objet fantaisie n'est pas nul, mais les variables de classe de l'objet fantaisie le sont et donc :

java.lang.AssertionError: The expected name is test, but the actual name is null

J'ai parcouru http://www.vogella.com/tutorials/Mockito/article.html mais je n'ai pas trouvé d'exemple de la manière de définir une variable de classe sur un objet fictif.

Comment puis-je simuler correctement l'objet film ? Plus généralement, est-ce la bonne façon de tester la classe MovieFinderImp ? J'ai été inspiré par ce blog pour tester les composants. https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4

(ps : je me demande si je dois vraiment tester movie.get() dans cette classe de test... peut-être que ma conception des tests est simplement mauvaise).

8voto

marians27 Points 251

Il y a un problème avec la façon dont vous faites une simulation dans une méthode @Before. Au lieu de

movieMock.setTitle("test");
movieMock.setDirector("directorTest");

Faites-le comme ça

Mockito.when(movieMock.getTitle()).thenReturn("test");
Mockito.when(movieMock.getDirector()).thenReturn("directorTest");

5voto

borjab Points 1839

Les objets fantaisie ne sont pas de vrais objets et n'ont pas de propriétés, seulement un comportement fantaisie que vous devez ajouter. L'utilisation du setter ne leur apportera rien. Le getter retournera null à moins que vous ne spécifiiez le comportement simulé. Cela peut être fait en utilisant la structure when... thenReturn :

when(movieMock.getTitle()).thenReturn("movie title");

Il n'y a peut-être aucune raison de se moquer de Movie. Vous pouvez utiliser le @Spy et de cette façon il sera un objet réel avec des propriétés réelles et en même temps vous pouvez surcharger certaines méthodes.

Les Mocks sont vraiment utiles lorsque la construction de l'objet complet est difficile et qu'il y a beaucoup de dépendances ou un comportement complexe, mais ils peuvent être superflus si Movie est un bean. Par exemple :

public class MovieFinderImplTest {

    @InjectMocks
    private MovieFinderImpl movieFinderImpl;

    @Spy /* <- See the change from mock */
    public Movie movie = new Movie();

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

        /* modified like a normal object */
        movie.setTitle("test");
        movie.setDirector("directorTest");
    }

Voir également le différence entre simulateur et espion . Il y a de longues discussions sur Internet sur ce qui doit être simulé et ce qui ne doit pas l'être. Si vous préférez toujours vous moquer de moview, alors la réponse de Marians27 et VinayVeluri est la bonne réponse pour vous.

2voto

VinayVeluri Points 4007

Voici ce que vous devez faire ;

import static org.mockito.Mockito.when;

when(movieMock.getTitle()).thenReturn("movie title");
when(movieMock.getDirector()).thenReturn("movie director");

@InjectMocks permet uniquement d'injecter des objets non nuls et ne traite pas les valeurs. Alors qu'avec les valeurs, nous devons explicitement définir les valeurs que nous devons tester.

Si vous utilisez, MockitoJunitRunner il n'est pas nécessaire d'appeler MockitoAnnotations.initMocks(this); dont le coureur s'occupe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X