2013-03-26 14 views
7

Uso la molla nella mia applicazione e voglio scrivere test unitari per tutte le mie classi. Chiaro alcuni servizi web esterni dalla mia applicazione e voglio prenderli in giro usando Mockito poiché voglio solo testare la mia funzionalità.Utilizzo di annotazioni Mockito con molla

Diciamo che ho il seguente scenario

Questa è la mia interfaccia webservice

public interface MyWebService { 
    public String getSomeData(int id); 
} 

uso il servizio di cui sopra in questo modo

public interface MyService { 
    int doSomethingElse(String str); 
} 

public class MyServiceImpl implements MyService { 

    private MyWebService myWebService; 

    int doSomethingElse(String str) { 
     ..... 
     myWebService.getSomeData(id); 
     ... 
    } 
} 

public interface MyService1 { 
    Stirng methodToBeTested(); 
} 


public class Class1 implements MyService1{ 
    @Resource 
    private MyService myService; 

    public Stirng methodToBeTested() { 
     myService.doSomethingElse(".."); 
    } 
} 

ho scritto il banco di prova uint come di seguito. Sto spiando MyService qui per eseguire il test unitario.

public class class1Test { 

    @Spy 
    MyService myService; 

    @Resource 
    @InjectMocks 
    Class1 class1; 

    public void setUPTest() { 
     MockitoAnnotations.initMocks(this); 
    Mockito.doReturn(123).when(myService).doSomethingElse("someString"); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
     this.setUPTest(); 
      ... 
      class1.methodToBeTested(); 
    } 

} 

Quando eseguo il test, quello che vedo è che, ottengo il valore dal webservice invece di quello che ho già detto, mentre lo sradicamento.

Qualcuno può aiutarmi con questo? (. E utile per esempio affermare la presenza o l'assenza di metodo transitiva invocazioni)

+0

Vedi anche http://stackoverflow.com/questions/2457239/injecting-mockito-mocks-into-a-spring-bean – Vadzim

risposta

5

ho risolto questo utilizzando la primavera Java config. Ho esteso il mio file di configurazione di default nel mio file di configurazione di test.

@Configuration 
    public class TestConfig extends DefaultConfig { 

     @Bean 
     public MyService myService() { 
     return Mockito.spy(new MyServiceImpl()); 
     } 
    } 

Ora la mia classe di test va come questo

public class class1Test { 

    @Resource 
    MyService myService; 

    @Resource 
    Class1 class1; 

    public void setUPTest() { 
     MockitoAnnotations.initMocks(this); 
    Mockito.doReturn(123).when(myService).doSomethingElse("someString"); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
     this.setUPTest(); 
      ... 
      class1.methodToBeTested(); 
    } 

} 
3

Un @Spy è usato per spiare ciò che accade quando si chiama servizi, ciò che si vuole è la @Mock della nota:

public class class1Test { 
    @Mock MyService myService; 
    ... 

Questa volontà risultato in tutti i metodi myService che restituiscono null, escludendo quelli con cui si esegue l'override con doReturn/when.

Per inciso, anziché chiamare setUpTest() dai metodi di prova, è necessario annotarlo con @Before.

Cheers,

+0

ho usato spia perché, ci sono altri metodi in MyService che il dosaggio deve essere stubato (questo è solo un codice di esempio che assomiglia al mio) – rahul

1

Questo dovrebbe adatta alle proprie esigenze:

@RunWith(MockitoJunitRunner.class) 
public class class1Test { 

    @Mock 
    private MyService myService; 

    private Class1 class1; 

    @Before 
    public void setUp() { 
     this.class1 = new Class1(myService); // creates this constructor. 
    } 

    @Test 
    public void methodToBeTestedTest() { 
     this.class1.methodToBeTested(); 
     Mockito.verify(this.myService).doSomethingElse(/* put expected arg here */); 
    } 
} 

Vedi anche il official doc.

2

Intendi anyString() anziché "someString" nel tuo metodo setUp? Questo può anche essere eq("someString") se si sta chiamando il metodo con una stringa specifica.

Dalla mia comprensione di Mockito non utilizzo spys poiché probabilmente indicano un problema di progettazione di classe. Perché non lo sei @Mock l'intero MyService, quindi;

@Mock MyService myService; 


public void setUpTest() { 
    MockitoAnnotations.initMocks(this); 
    when(myService.doSomethingElse(anyString)).thenReturn(123); 
} 
+0

@coder Ho avuto un design di classe simile fino a quando non sono venuto a testarlo quando ho capito che la mia classe era fare troppe cose rendendo difficile il test unitario. Prendi in considerazione di suddividere il servizio web in una classe di gestori. In questo modo puoi costruire la tua classe con il gestore di finte e eliminare il '' '' @ Spy''''. Qualsiasi chiamata alla w può quindi essere semplicemente derisa con i tradizionali strumenti non-spia. – OceanLife

+0

Ciò risolverebbe il problema ma la cosa triste è che non posso modificare l'implementazione originale di MyService o MyServiceImpl. – rahul

+0

Ah, sì, sei corretto usare una spia allora. Non ho capito. Sono particolarmente utili quando si tratta di codice di terze parti/legacy. Il mio consiglio sui Matchers offre migliori risultati di derisione? – OceanLife

1

Modified,

public class class1Test { 

    @Mock 
    private MyService myService; 

    private Class1 class1; 

    @Before 
    public void onceBeforeEachTest() { 
     MockitoAnnotations.initMocks(this); 
     this.class1 = new Class1(myService); 
     Mockito.when(myService).doSomethingElse(anyString()).thenReturn(123); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
      class1.methodToBeTested(); 
    } 
} 
+0

Non ho un costruttore che accetta un oggetto come parametro. – rahul

3

Per sostituire il tuo fagioli con finto in un certo uso di test Springockito o meglio Springockito-annotations.

Qualcosa del genere dovrebbe funzionare:

@ContextConfiguration(loader = SpringockitoContextLoader.class, 
    locations = "classpath:/context.xml") 
public class SpringockitoAnnotationsMocksIntegrationTest extends AbstractJUnit4SpringContextTests { 

    @WrapWithSpy 
    private MyService innerBean; 

    @Resource 
    Class1 class1; 

    public void setUPTest() {   
     Mockito.doReturn(123).when(myService).doSomethingElse("someString"); 
    } 

    @Test 
    public void methodToBeTestedTest() { 
    this.setUPTest(); 
     ... 
     class1.methodToBeTested(); 
    } 

}

+0

Ho visto il link qui sopra. Come faccio a iniettare "myService" spy in "class1" usando springockito. In Class1, "MyService" è privato e non ha setter. – rahul

+0

@coder, aggiornato. Se nel tuo contesto reale myService viene iniettato in Class1 - verrà iniettato anche con WrapWithSpy. –

+0

Sto usando spring java config per l'inizializzazione dei fagioli, springockito dosent support it. – rahul

Problemi correlati