2015-06-11 5 views
29

Zum Beispiel habe ich Handler:Wie kann ich Methoden der @InjectMocks-Klasse verspotten?

@Component 
public class MyHandler { 

    @AutoWired 
    private MyDependency myDependency; 

    public int someMethod() { 
    ... 
    return anotherMethod(); 
    } 

    public int anotherMethod() {...} 
} 

, um es zu testen ich so etwas schreiben wollen:

@RunWith(MockitoJUnitRunner.class} 
class MyHandlerTest { 

    @InjectMocks 
    private MyHandler myHandler; 

    @Mock 
    private MyDependency myDependency; 

    @Test 
    public void testSomeMethod() { 
    when(myHandler.anotherMethod()).thenReturn(1); 
    assertEquals(myHandler.someMethod() == 1); 
    } 
} 

Aber es ruft tatsächlich anotherMethod() wenn ich versuche, es zu verspotten. Was soll ich mit myHandler tun, um seine Methoden zu verspotten?

+0

Wenn Sie MyHandler testen wollen, shouldn Sie Mach keine eigenen Methoden vor (da du deinen Handler testen willst, nicht den Mock). Gibt es einen bestimmten Grund, warum Sie dies tun müssen? – Nitek

Antwort

55

Erste Der Grund für das Meckern von MyHandler-Methoden kann folgender sein: Wir testen bereits anotherMethod() und es hat komplexe Logik, also warum müssen wir es erneut testen (wie ein Teil von someMethod()) wenn wir nur verify anrufen können, dass es anruft?
Wir können es durch:

@RunWith(MockitoJUnitRunner.class} 
class MyHandlerTest { 

    @Spy 
    @InjectMocks 
    private MyHandler myHandler; 

    @Mock 
    private MyDependency myDependency; 

    @Test 
    public void testSomeMethod() { 
    doReturn(1).when(myHandler).anotherMethod(); 
    assertEquals(myHandler.someMethod() == 1); 
    verify(myHandler, times(1)).anotherMethod(); 
    } 
} 

Hinweis: Bei ‚Spionage‘ Objekt brauchen wir doReturn statt thenReturn zu verwenden (kleine Erklärung ist here)

0

In Ihrem Code testen Sie MyHandler überhaupt nicht. Sie möchten nicht vortäuschen, was Sie testen, Sie möchten die tatsächlichen Methoden aufrufen. Wenn MyHandler Abhängigkeiten hat, verspotten Sie sie.

Etwas wie folgt aus:

public interface MyDependency { 
    public int otherMethod(); 
} 

public class MyHandler { 
    @AutoWired 
    private MyDependency myDependency; 

    public void someMethod() { 
    myDependency.otherMethod(); 
    } 
} 

Und in Test:

private MyDependency mockDependency; 
private MyHandler realHandler; 

@Before 
public void setup() { 
    mockDependency = Mockito.mock(MyDependency.class); 
    realHandler = new MyHandler(); 
    realhandler.setDependency(mockDependency); //but you might Springify this 
} 

@Test 
public void testSomeMethod() { 

    //specify behaviour of mock 
    when(mockDependency.otherMethod()).thenReturn(1); 

    //really call the method under test 
    realHandler.someMethod(); 
} 

Der Punkt ist wirklich die Methode im Test zu rufen, sondern verspotten alle Abhängigkeiten sie haben können (zB Aufruf der Methode von anderen Klassen)

Wenn diese anderen Klassen Teil Ihrer Anwendung sind, haben sie ihre eigenen Komponententests.

HINWEIS der obige Code könnte mit mehr Anmerkungen verkürzt werden, aber ich wollte es noch deutlicher aus Gründen der Erklärung machen (und auch ich erinnere mich nicht, was die Anmerkungen sind :))

+0

Erstellen einer Instanz unter Verwendung von Feder-IOC. Sie profitieren nicht vom Frühjahr IOC. Angenommen, ich muss einen anderen Dienst injizieren. Ich kann das nicht tun. Ich muss eine Instanz erstellen. –

Verwandte Themen