Was ist der Unterschied zwischen @Mock
und @InjectMocks
im Mockito-Framework?
Antworten
Zu viele Anzeigen?Ein "Mocking-Framework", auf dem Mockito basiert, ist ein Framework, das es Ihnen ermöglicht, Mock-Objekte zu erstellen (in alten Begriffen könnten diese Objekte als Schüttel bezeichnet werden, da sie als Schüttel für abhängige Funktionalitäten arbeiten) Mit anderen Worten, ein Mock-Objekt wird verwendet, um das reale Objekt zu imitieren, von dem Ihr Code abhängt. Sie erstellen ein Proxy-Objekt mit dem Mocking-Framework. Durch die Verwendung von Mock-Objekten in Ihren Tests gehen Sie im Grunde von normalen Unittests zu Integrationstests über
Mockito ist ein Open-Source-Test-Framework für Java, das unter der MIT-Lizenz veröffentlicht wurde. Es ist ein "Mocking-Framework", das es Ihnen ermöglicht, schöne Tests mit einer sauberen und einfachen API zu schreiben. Es gibt viele verschiedene Mocking-Frameworks im Java-Bereich, jedoch gibt es im Wesentlichen zwei Haupttypen von Mock-Objekt-Frameworks, solche, die über Proxy implementiert werden und solche, die über Klassen-Remapping implementiert werden.
Dependency Injection-Frameworks wie Spring ermöglichen es Ihnen, Ihre Proxy-Objekte einzufügen, ohne Code zu ändern. Das Mock-Objekt erwartet, dass eine bestimmte Methode aufgerufen wird, und gibt ein erwartetes Ergebnis zurück.
Die @InjectMocks
Annotation versucht, die Testobjektinstanz zu instanziieren und injiziert Felder, die mit @Mock
oder @Spy
annotiert sind, in private Felder des Testobjekts.
Der MockitoAnnotations.initMocks(this)
Aufruf setzt das Testobjekt zurück und initialisiert die Mocks neu, also denken Sie daran, dies bei Ihrer @Before
/ @BeforeMethod
Annotation zu haben.
Auch wenn die oben genannten Antworten abgedeckt haben, habe ich gerade versucht, winzige Details hinzuzufügen, die mir fehlen. Der Grund dafür (Das Warum).
Illustration:
Sample.java
---------------
public class Sample{
DependencyOne dependencyOne;
DependencyTwo dependencyTwo;
public SampleResponse methodOfSample(){
dependencyOne.methodOne();
dependencyTwo.methodTwo();
...
return sampleResponse;
}
}
SampleTest.java
-----------------------
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassA.class})
public class SampleTest{
@InjectMocks
Sample sample;
@Mock
DependencyOne dependencyOne;
@Mock
DependencyTwo dependencyTwo;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
public void sampleMethod1_Test(){
//Ordnen Sie die Abhängigkeiten
DependencyResponse dependencyOneResponse = Mock(sampleResponse.class);
Mockito.doReturn(dependencyOneResponse).when(dependencyOne).methodOne();
DependencyResponse dependencyTwoResponse = Mock(sampleResponse.class);
Mockito.doReturn(dependencyOneResponse).when(dependencyTwo).methodTwo();
//Rufen Sie die zu testende Methode auf
SampleResponse sampleResponse = sample.methodOfSample()
//Assert
}
}
Ein Vorteil bei dem von @Tom erwähnten Ansatz ist, dass Sie keine Konstruktoren im SomeManager erstellen müssen und somit die Klienten daran hindern, es zu instanziieren.
@RunWith(MockitoJUnitRunner.class)
public class SomeManagerTest {
@InjectMocks
private SomeManager someManager;
@Mock
private SomeDependency someDependency; // dieser wird in someManager injiziert
//Sie müssen den SomeManager überhaupt nicht mit dem Standardkonstruktor instanziieren
//SomeManager someManager = new SomeManager();
//Oder SomeManager someManager = new SomeManager(someDependency);
//Tests...
}
Ob es eine gute Praxis ist oder nicht, hängt von Ihrem Anwendungsdesign ab.
@Mock
wird verwendet, um die Referenzen der abhängigen Beans zu deklarieren/mocks, während @InjectMocks
verwendet wird, um die Bean zu mocken, für die der Test erstellt wird.
Zum Beispiel:
public class A{
public class B b;
public void doSomething(){
}
}
Test für Klasse A
:
public class TestClassA{
@Mocks
public class B b;
@InjectMocks
public class A a;
@Test
public testDoSomething(){
}
}
Die @InjectMocks-Annotation kann verwendet werden, um Mock-Felder automatisch in ein Testobjekt einzufügen.
In folgendem Beispiel wurde @InjectMocks verwendet, um die Mock-DatenMap in die dataLibrary einzufügen.
@Mock
Map dataMap;
@InjectMocks
DataLibrary dataLibrary = new DataLibrary();
@Test
public void whenUseInjectMocksAnnotation_() {
Mockito.when(dataMap.get("aData")).thenReturn("aMeaning");
assertEquals("aMeaning", dataLibrary.getMeaning("aData"));
}