Ich habe erst heute angefangen, etwas über Mockito zu lernen. Ich habe einen einfachen Test geschrieben (mit JUnit, siehe unten), aber ich kann nicht herausfinden, wie ich Scheinobjekte in Spring's verwalteten Beans verwenden kann. Was sind Best Practices für die Arbeit mit Spring ? Wie soll ich meiner Bohne eine verspottete Abhängigkeit hinzufügen?
Sie können dies bis zu meiner Frage überspringen .
Zuallererst, was ich gelernt habe. Dies ist ein sehr guter Artikel über Mocks Aren't Stubs , in dem die Grundlagen erläutert werden (Mock überprüft das Verhalten und nicht den Status ). Dann gibt es hier ein gutes Beispiel, Mockito, und hier, leichter mit Mockito verspotten . Wir haben eine Erklärung, dass Mockitos Scheinobjekte sowohl Schein- als auch Stummelobjekte sind .
Hier Mockito und hier Matchers finden Sie weitere Beispiele.
Dieser Test
@Test
public void testReal(){
List<String> mockedList = mock(List.class);
//stubbing
//when(mockedList.get(0)).thenReturn("first");
mockedList.get(anyInt());
OngoingStubbing<String> stub= when(null);
stub.thenReturn("first");
//String res = mockedList.get(0);
//System.out.println(res);
//you can also verify using argument matcher
//verify(mockedList).get(anyInt());
verify(mockedList);
mockedList.get(anyInt());
}
funktioniert gut.
Zurück zu meiner Frage. Hier Mockito-Mocks in eine Spring Bean injizieren, versucht jemand, Springs zu verwenden ReflectionTestUtils.setField()
, aber hier haben wir Spring-Integrationstests, Erstellen von Mock-Objekten. Wir empfehlen, den Spring-Kontext zu ändern .
Ich habe die letzten beiden Links nicht wirklich verstanden ... Kann mir jemand erklären, welches Problem Spring mit Mockito hat? Was ist los mit dieser Lösung?
@InjectMocks
private MyTestObject testObject
@Mock
private MyDependentObject mockedObject
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
https://stackoverflow.com/a/8742745/1137529
EDIT : Ich war nicht wirklich klar. Ich werde 3 Beispiele für Code bereitstellen, um mich selbst zu verdeutlichen: Angenommen, wir haben Bean HelloWorld mit Methode printHello()
und Bean HelloFacade mit Methode sayHello
, die Aufrufe an die HelloWorld-Methode weiterleiten printHello()
.
Das erste Beispiel ist die Verwendung des Spring-Kontexts und ohne benutzerdefinierten Runner unter Verwendung von ReflectionTestUtils für die Abhängigkeitsinjektion (DI):
public class Hello1Test {
private ApplicationContext ctx;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml");
}
@Test
public void testHelloFacade() {
HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class);
HelloWorld mock = mock(HelloWorld.class);
doNothing().when(mock).printHello();
ReflectionTestUtils.setField(obj, "hello", mock);
obj.sayHello();
verify(mock, times(1)).printHello();
}
}
Wie @Noam hervorhob, gibt es eine Möglichkeit, es ohne expliziten Aufruf auszuführen MockitoAnnotations.initMocks(this);
. Ich werde in diesem Beispiel auch den Kontext des Frühlings verwenden.
@RunWith(MockitoJUnitRunner.class)
public class Hello1aTest {
@InjectMocks
private HelloFacade obj = new HelloFacadeImpl();
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
Ein anderer Weg, dies zu tun
public class Hello1aTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@InjectMocks
private HelloFacadeImpl obj;
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
Nichts, dass wir in einem früheren Beispiel HelloFacadeImpl manuell instanziieren und HelloFacade zuweisen müssen, da HelloFacade eine Schnittstelle ist. Im letzten Beispiel können wir einfach HelloFacadeImpl deklarieren und Mokito wird es für uns instanziieren. Der Nachteil dieses Ansatzes besteht darin, dass die zu testende Einheit jetzt eine implizite Klasse und keine Schnittstelle ist.
@InjectMocks
(relativ neu, obwohl IIRC vor diesem Blog-Beitrag). Daher kann es vorkommen, dass die Bean-Definitionen neu angeordnet werden müssen. Ich bin mir nicht sicher, was die Frage letztendlich ist.