2012-11-30 6 views
8

Ho una chiamata dao.create() che desidero simulare durante il test di un metodo. Ma mi manca qualcosa mentre sto ancora ricevendo NPE. Cosa c'è di sbagliato qui?Come prendere in giro una variabile dao privata?

class MyService { 
    @Inject 
    private Dao dao; 

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

Come posso prendere in giro la chiamata 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

La classe "DAO" o "Dao"? – fgb

+0

Alcune buone soluzioni dipendono dal framework di iniezione delle dipendenze che si sta utilizzando. Si prega di aggiungere un tag appropriato (guice, primavera, ...) –

risposta

5

Non si sta iniettando il DAO. Con mockito puoi cambiare la tua classe di test per usare @InjectMocks e usare mockito runner.

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

Si può leggere di più su InjectMocks a Inject Mocks API

Più semplice modo sta cambiando la vostra iniezione per iniezione per costruttore. Ad esempio, cambierai MyService a

class MyService { 
    ... 
    private final Dao dao; 

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

quindi il tuo test potresti passare il DAO deriso nel setup.

... 
@Mock 
private Dao dao; 

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

ora è possibile utilizzare verify per verificare se create è stato chiamato, come:

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

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

Usando l'iniezione dal costruttore permette le dipendenze più chiara ad altri sviluppatori e vi aiuterà quando la creazione di test :)

+0

Mi dispiace per il povero inglese: P –

+1

l'inglese non è poi così male e mi aiuta molto. Grazie! – membersound

1

Hai ancora bisogno di impostare il campo dao con il tuo finto. È possibile utilizzare il riflesso su questo.

1

È necessario iniettare/impostare l'oggetto mocked DAO nella classe di servizio.

Se si tratta di un progetto basato primavera, si può avere uno sguardo @ Spring Junit TestRunner

0

Se si utilizza new MyService() il Tao non è mai iniettato. Per iniettare il Dao è necessario caricare MyService tramite ApplicationContext (Spring) o Injector (Guice). Come faresti nella tua normale applicazione.

0

Come altri hanno già detto, è necessario impostare il campo nella classe MyService in qualche modo. Non sono sicuro che il meccanismo consenta a un corridore composto per il test di utilizzare sia Powermock sia un runner di framework (supponendo che sia necessario Powermock), ma finché si utilizza già PowerMock (per motivi non chiari nell'esempio fornito) , puoi avvalerti della classe Whitebox per impostare manualmente il dao.

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