2015-06-11 12 views
29

Na przykład mam Handler:Jak mogę pozorować metody klasy @InjectMocks?

@Component 
public class MyHandler { 

    @AutoWired 
    private MyDependency myDependency; 

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

    public int anotherMethod() {...} 
} 

do testowania go chcę napisać coś takiego:

@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); 
    } 
} 

Ale faktycznie nazywa anotherMethod() gdy próbuję go wyśmiewać. Co należy zrobić z myHandler, aby kpić z jego metod?

+0

Jeśli chcesz przetestować MyHandler, to powinnam nie kpisz z własnych metod (ponieważ chcesz przetestować swojego handlarza, a nie próbę). Czy istnieje konkretny powód, dla którego musisz to zrobić? – Nitek

Odpowiedz

55

Pierwszy z całego powodu kpiny z MyHandler metody mogą być następujące: testujemy już anotherMethod() i ma złożoną logikę, więc dlaczego musimy przetestować go ponownie (jak część someMethod()), czy możemy po prostu verify, że dzwoni?
Możemy to zrobić poprzez:

@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(); 
    } 
} 

Uwaga: w przypadku „szpiegowskiej” obiektu musimy użyć doReturn zamiast thenReturn (małe wyjaśnienie jest here)

0

W swoim kodzie nie testujesz MyHandler w ogóle. Nie chcesz drwić z tego, co testujesz, chcesz nazwać jego rzeczywiste metody. Jeśli MyHandler ma zależności, wyśmiewasz je.

coś takiego:

public interface MyDependency { 
    public int otherMethod(); 
} 

public class MyHandler { 
    @AutoWired 
    private MyDependency myDependency; 

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

A w teście:

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(); 
} 

Chodzi o to, aby rzeczywiście wywołać metodę badanego, ale wyśmiewać wszelkie zależności mogą mieć (np wywołanie metody z innego klasy)

Jeśli te inne klasy będą częścią twojego wniosku, będą miały własne testy jednostkowe.

UWAGA powyższy kod może zostać skrócony z kilku adnotacji, ale chciałem, aby to bardziej wyraźne w trosce o wyjaśnienie (i też nie mogę sobie przypomnieć, co adnotacje są :))

+0

Tworzenie instancji przy użyciu sprężyny IOC. Nie czerpiecie korzyści ze sprężynowego IOC. Załóżmy, że jeśli muszę wstrzyknąć inną usługę. Nie mogę tego zrobić. Muszę stworzyć instancję. –

Powiązane problemy