2012-11-30 7 views
8

Mam wywołanie dao.create(), które chcę kpić podczas testowania metody. Ale brakuje mi czegoś, ponieważ wciąż otrzymuję NPE. Co jest nie tak?Jak wyśmiać prywatną zmienną dao?

class MyService { 
    @Inject 
    private Dao dao; 

    public void myMethod() { 
     //.. 
     dao.create(object); 
     // 
    } 
} 

Jak wyśmiać wywołanie dao.create()?

@RunWith(PowerMockRunner.class) 
@PrepareForTest(DAO.class) 
public void MyServiceTest { 

    @Test 
    public void testMyMethod() { 
     PowerMockito.mock(DAO.class); 

     MyService service = new MyService(); 
     service.myMethod(); //NPE for dao.create() 
    } 
} 
+0

Czy klasa "DAO" lub "Dao"? – fgb

+0

Niektóre dobre rozwiązania zależą od używanej struktury wtrysku zależności. Dodaj odpowiedni tag (guice, spring, ...) –

Odpowiedz

5

Nie wstrzykujesz DAO. Za pomocą mockito możesz zmienić klasę testową na @InjectMocks i użyć mockito runner.

@RunWith(MockitoJUnitRunner.class) 
public void MyServiceTest { 
    @Mock 
    private Dao dao; 
    @InjectMocks 
    private MyService myService; 
    ... 
} 

Możesz przeczytać więcej o InjectMocks na Inject Mocks API

prostszy sposób zmienia swój zastrzyk wstrzyknięciem przez konstruktora. Na przykład zmieniłbyś MyService na

class MyService { 
    ... 
    private final Dao dao; 

    @Inject 
    public MyService(Dao dao) { 
     this.dao = dao; 
    } 
    ... 
} 

to twój test, który możesz łatwo przekazać wyśmiewanym DAO w konfiguracji.

... 
@Mock 
private Dao dao; 

@Before 
public void setUp() { 
    this.dao = mock(Dao.class); 
    this.service = new MyService(dao); 
} 
... 

teraz można używać verify aby sprawdzić, czy create nazwano, jak:

... 
    verify(dao).create(argThat(isExpectedObjectBeingCreated(object))); 
} 

private Matcher<?> isExpectedObjectBeingCreated(Object object) { ... } 

użyciu iniekcji przez konstruktora będzie pozwól zależności wyraźniejszy do innych deweloperów i pomoże przy tworzeniu testów :)

+0

Przepraszam za słaby angielski: P –

+1

Ci angielski nie jest taki zły i pomaga mi dużo. dzięki! – membersound

1

Nadal trzeba ustawić pole dao z próbą. Możesz użyć refleksji do tego.

1

Musisz wstrzyknąć/ustawić wyśmiewany obiekt DAO w swojej klasie usług.

Jeśli jest to projekt oparty sprężyna, można spojrzeć @ Wiosna JUnit TestRunner

0

Jeśli używasz new MyService() Tao nie jest wstrzykiwany. Aby wstrzyknąć Dao, musisz załadować MyService poprzez ApplicationContext (Spring) lub Injector (Guice). Tak jak w normalnej aplikacji.

0

Jak już powiedzieli inni, musisz ustawić pole dao w klasie MyService w pewien sposób. Nie jestem pewien mechanizmu, który pozwoli biegaczowi złożonemu na twoim teście używać zarówno Powermock, jak i DI runnera (zakładając, że Powermock jest wymagany), ale tak długo, jak już używasz PowerMocka (z powodów niejasnych w podanym przykładzie) , możesz skorzystać z klasy Whitebox, aby ustawić dao bardziej ręcznie.

public void testMyMethod() { 
    Dao dao = mock(Dao.class) 
    doNothing().when(dao).create(anyObject())); //assuming no return val for dao.create() 

    MyService service = new MyService(); 
    Whitebox.setInternalState(service, "dao", dao); 

    service.myMethod(); 
}