80 votes

Plusieurs niveaux de @Mock et @InjectMocks

Donc je comprends que dans Mockito @InjectMocks injectera tout ce qu'il peut avec l'annotation de @Mock, mais comment gérer ce scénario ?

@Mock
private MockObject1 mockObject1;

@Mock
private MockObject2 mockObject2;

@InjectMocks
private SystemUnderTest systemUnderTest = new SystemUnderTest();

Imaginez que MockObject2 a un attribut qui est de type MockObject1, et que SystemUnderTest a un attribut de type MockObject2. Je voudrais que MockObject1 soit injecté dans MockObject2, et que MockObject2 soit injecté dans SystemUnderTest.

Est-ce possible avec les annotations ?

1 votes

Vous ne semblez pas utiliser Spring, sinon il est assez facile de simuler un bean (quel que soit le niveau de simulation) en utilisant "@MockBean" au lieu de "@Mock".

56voto

Collin Peters Points 748

N'ayant pas obtenu de réponse ici, j'ai posé la question sur les forums de Mockito. Voici un lien vers la discussion : https://groups.google.com/d/topic/mockito/hWwcI5UHFi0/discussion

Pour résumer les réponses, techniquement, cela irait à l'encontre du but de la moquerie. Vous ne devez vraiment simuler que les objets nécessaires à la classe SystemUnderTest. Il est inutile de simuler des choses dans des objets qui sont eux-mêmes simulés.

Si vous voulez vraiment le faire, @spy peut vous aider.

16 votes

Oui, ce n'est pas approprié pour unité où le mocking est utilisé, mais cette fonctionnalité (injecter des dépendances jusqu'en bas) peut être très utile pour intégration des tests. J'y travaille actuellement pour ma propre boîte à outils de simulation, JMockit.

31voto

MattC Points 478

C'est possible en combinant @Spy avec @InjectMocks. Pour votre exemple, ce serait :

@Spy
private MockObject1 mockObject1 = new MockObject1 ();

@Spy @InjectMocks //if MockObject2 has a MockObject1, then it will be injected here.
private MockObject2 mockObject2 = new MockObject2 ();

@InjectMocks
private SystemUnderTest systemUnderTest;

10 votes

20voto

z1lV3r Points 429

Une autre solution que j'ai trouvée est d'utiliser l'annotation java sintax instead pour rendre l'objet @Spy injecté.

@Spy
private MockObject1 mockObject1 = new MockObject1 ();

@InjectMocks //if MockObject2 has a MockObject1, then it will be injected here.
private MockObject2 mockObject2 = spy(MockObject2.class);

@InjectMocks
private SystemUnderTest systemUnderTest;

3voto

razvang Points 736

Voici ma solution :

@ExtendWith(SpringExtension.class)
class DocumentServiceTestMock {

//2nd Level Dependency
CustomerFacade customerFacade = Mockito.mock(CustomerFacade.class);

//Direct Dependency
@Spy
PostCreateHelper postCreateHelper = new PostCreateHelper(customerFacade);

//SUT
@InjectMocks
DocumentService documentService;

@BeforeEach
void setUp() {
        given(customerFacade.getString()).willReturn("customerFacade_MOCKED");
}

@Test
void test() {
     String documentAsResource = documentService.getDocumentAsResource(ExportType.WORD);
}
//----------
@Service
public class DocumentService {
   final PostCreateHelper postCreateHelper;

@Component
public class PostCreateHelper {
   final CustomerFacade customerFacade;

@Service
public class CustomerFacade {

3voto

penghuo Points 62

Cela fonctionne pour moi :

private MockObject1 mockObject1 = mock(MockObject1.class);

@Spy
private RealObject2 realObject = new RealObject2(mockObject1);

@InjectMocks
private SystemUnderTest systemUnderTest = new SystemUnderTest();

0 votes

Il ne s'agit cependant pas vraiment d'une injection, puisque vous envoyez simplement votre MockObject1 à MockObject2 en utilisant le constructeur.

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