2013-03-05 22 views
16

Ecco la mia domanda:Come funziona Mockito @InjectMocks?

Ho diverse classi di servizi Web per verificare che tutti ereditino i loro metodi da un servizio generico. Piuttosto che scrivere un test unitario per ciascuno, immagino di poter rompere la suite di test in base a aree funzionali (cioè tre gruppi di metodi di test, ciascuno basato su una chiamata al metodo DAO sottostante).

Quello che mi propongo di fare è:

@Mock StateDAO mockedStateDao; 
@Mock CountyDAO mockedCountyDao; 
@Mock VisitorDAO mockedVisitorDao; 

quindi chiamare:

@InjectMocks CountyServiceImpl<County> countyService = new CountyServiceImpl<County>(); 
@InjectMocks StateServiceImpl<State> stateService = new StateServiceImpl<State>(); 
@InjectMocks VisitorServiceImpl<Visitor> visitorService = new VisitorServiceImpl<Visitor>(); 

Come posso essere sicuro che ogni mockedDAO verrà iniettato nel servizio corretto? Sarebbe più facile eseguire l'autowire su tutti e tre (invece di usare @InjectMocks)?

sto usando Spring, Hibernate, e Mockito ...

+0

cercherò di fare questo all'interno di una classe di test. – DYezek

+0

Inoltre, ho già gli elementi per @InjectMocks nel file Spring test-application-context.xml (quindi potrei autoprodarli). Non sono sicuro della differenza tra l'autowiring e l'iniezione di mock. – DYezek

+1

Modifica la domanda originale per aggiungere contenuti aggiuntivi anziché lasciare commenti sulla tua domanda. – ArtB

risposta

0

Nevermind, sembrava online- i InjectMocks annotazione Tratta nulla con l'annotazione @Mock come un campo e è statico con ambito (classe di larghezza), in modo da Davvero non potevo garantire che i burloni sarebbero andati al servizio corretto. questo è stato un po 'un esperimento mentale per provare il test unitario a livello di funzionalità piuttosto che a livello di classe. Suppongo che mi autowire questa roba con Spring ...

1

Bene, il metodo statico MockitoAnnotations.initMocks(Object) viene utilizzato per avviare l'intero processo.

non so per certo come funziona, come non ho navigato il codice sorgente, ma vorrei applicarla o meno così:

  1. eseguire la scansione del passato classe Object s' per le variabili membro con l'annotazione @Mock.
  2. Per ognuno, creare una simulazione di quella classe e impostarla su quel membro.
  3. Analizza la classe passata di Object per le variabili membro con l'annotazione @InjectMocks.
  4. Analizza la classe di ogni membro trovato per i membri che può essere iniettata con uno degli oggetti di simulazione creati in (2) (ovvero, dove il campo è una classe/interfaccia padre o la stessa classe, come mock oggetti dichiarati classe) e impostarlo su quel membro.
19

Nicholas Bene risposta è quasi corretto, ma invece di indovinare basta guardare il javadoc di InjectMocks, contiene maggiori dettagli;)

Per me è strano avere così tanti servizi in un singolo test, è non sembra giusto, come test unitario o test di integrazione. Nel test unitario è sbagliato, perché hai troppi collaboratori, non sembra orientato agli oggetti (o SOLID). Nei test di integrazione, è strano perché il codice che testate l'integrazione con il DB non lo prende in giro.

Per un riferimento rapido 1.9.5 si hanno:

Mark un campo su cui deve essere eseguita l'iniezione.

Consente la simulazione di stenografia e iniezione spia. Riduce al minimo l'iniezione ripetitiva di finte e spie. Mockito proverà a iniettare mock solo per iniezione del costruttore, iniezione setter o iniezione di proprietà in ordine e come descritto di seguito. Se una delle seguenti strategie fallisce, allora Mockito non segnalerà un errore; Dovresti fornire da solo le dipendenze.

  1. Iniezione del costruttore; viene scelto il costruttore più grande, quindi gli argomenti vengono risolti con i mock dichiarati solo nel test.

    Nota: Se non è possibile trovare gli argomenti, viene passato null. Se si desiderano tipi non simulabili, l'iniezione del costruttore non avverrà. In questi casi, dovrai soddisfare te stesso le dipendenze.

  2. Iniezione setter; le mazze verranno prima risolte per tipo, quindi, se sono presenti più proprietà dello stesso tipo, dalla corrispondenza del nome della proprietà e del nome fittizio.

    Nota 1: Se si dispone gli oggetti con lo stesso tipo (o lo stesso cancellazione), è meglio chiamare tutti i campi annotati @Mock con gli immobili compatibili, altrimenti Mockito potrebbe confondersi e l'iniezione non accadrà.

    Nota 2: Se l'istanza @InjectMocks non è stata inizializzata prima e dispone di un costruttore no-arg, verrà inizializzata con questo costruttore.

  3. Iniezione di campo; le mazze verranno prima risolte per tipo, quindi, se ci sono diverse proprietà dello stesso tipo, dalla corrispondenza del nome del campo e del nome fittizio.

    Nota 1: Se si dispone di campi con lo stesso tipo (o lo stesso cancellazione), è meglio chiamare tutti i campi annotati @Mock con i campi corrispondenti, altrimenti Mockito potrebbe confondersi e l'iniezione non accadrà.

    Nota 2: Se l'istanza @InjectMocks non è stata inizializzata prima e dispone di un costruttore no-arg, verrà inizializzata con questo costruttore.

3

Se si dispone di più servizi e vorrebbe sostituire i DAO con Mock-oggetti in un ambiente basato Primavera-, mi sento di raccomandare di utilizzare Springockito: https://bitbucket.org/kubek2k/springockito/wiki/Home

anch'essa menzionata qui: Injecting Mockito mocks into a Spring bean

tuo TestClass quindi potrebbe essere simile a questo:

@RunWith (SpringJUnit4ClassRunner.class) 
@ContextConfiguration (loader = SpringockitoContextLoader.class, locations = {"classpath:/org/example/package/applicationContext.xml"}) 
public class NameOfClassTest { 

    @Autowired 
    @ReplaceWithMock 
    StateDAO mockedStateDao; 

    @Autowired 
    @ReplaceWithMock 
    CountyDAO mockedCountyDao; 

    @Autowired 
    @ReplaceWithMock 
    VisitorDAO mockedVisitorDao; 

Nella tua @Test o @Before Methode È possibile regolare il deride il modo standard di Mockito:

Mockito.doReturn(null).when(mockedCountyDao).selectFromDB(); 
Problemi correlati