2015-09-28 16 views
9

Sto cercando di scrivere un test per la classe questo di Java SpringBoot:Mock metodo oggetto chiamata utilizzando primavera Boot e Mockito

https://github.com/callistaenterprise/blog-microservices/blob/master/microservices/composite/product-composite-service/src/main/java/se/callista/microservices/composite/product/service/ProductCompositeIntegration.java

In particolare, sto cercando di questa chiamata al metodo "finto" :

URI uri = util.getServiceUrl("product"); 

ho capito che dovrei "finto" l'oggetto ServiceUtils al fine di fare questo. Ho provato questo utilizzando le @Mock e @InjectMocks annotazioni:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = ProductCompositeServiceApplication.class) 
public class ProductCompositeIntegrationTest { 

    @InjectMocks 
    @Autowired 
    private ProductCompositeIntegration productIntegration; 

    @Autowired 
    private RestTemplate restTemplate; 

    @Mock 
    private ServiceUtils util; 

    private MockRestServiceServer mockServer; 

    @Before 
    public void setUp() { 
     MockitoAnnotations.initMocks(this); 
     mockServer = MockRestServiceServer.createServer(restTemplate); 
    } 

    @Test 
    public void myTest() { 
     Mockito.when(util.getServiceUrl("product")).thenReturn(URI.create("http://localhost:8080/test")); 
     ResponseEntity<Iterable<Product>> products = productIntegration.getAllProducts(); 
    } 
} 

Ma in questo modo si chiama ancora il ServiceUtils oggetto originale, e non il "deriso" uno. Anche provato senza l'annotazione @Autowired allo ProductCompositeIntegration, ma questo si traduce in un NullPointerException.

Cosa sto sbagliando?


mia classe principale appare così:

@SpringBootApplication 
@EnableCircuitBreaker 
@EnableDiscoveryClient 
public class ProductCompositeServiceApplication { 
    public static void main(String[] args) { 
     SpringApplication.run(ProductCompositeServiceApplication.class, args); 
    } 
} 

L'oggetto ServiceUtils che sto cercando di prendere in giro è specificato in una classe, annotato con @Component annotazioni di primavera per iniettare in altre classi utilizzando @Autowired .

risposta

7

Dopo molte prove ed errori sono riuscito a risolvere questo problema.

ho lasciato cadere le annotazioni

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = ProductCompositeServiceApplication.class) 

aboved la classe di test.

ho segnato la classe che stavo testando con @InjectMocks e le dipendenze con @Mock:

public class ProductCompositeIntegrationTest { 
    @InjectMocks 
    private ProductCompositeIntegration productIntegration; 

    @Mock 
    private ServiceUtils util; 

    private MockRestServiceServer mockServer; 

    private RestTemplate restTemplate = new RestTemplate(); 

    @Before 
    public void init() { 
     MockitoAnnotations.initMocks(this); 
     mockServer = MockRestServiceServer.createServer(restTemplate); 
     productIntegration.setRestTemplate(restTemplate); 
    } 

    @Test 
    public void someTests() { 
     when(util.getServiceUrl("product")).thenReturn(URI.create("http://localhost:8080/test")); 
     //Test code... 
    } 
} 

Non sono sicuro se questo è l'approccio migliore ("la via Primavera"), ma questo ha lavorato per me.

Questo articolo ha reso tutto chiaro per me: http://rdafbn.blogspot.be/2014/01/testing-spring-components-with-mockito.html

+1

Mi è piaciuto il tuo approccio. Era esattamente quello che stavo cercando. – user2957378

0

dovete scrivere un FactoryBean come

public class MockitoFactoryBean<T> implements FactoryBean<T> { 

private Class<T> classToBeMocked; 

public MockitoFactoryBean(Class<T> classToBeMocked) { 
    this.classToBeMocked = classToBeMocked; 
} 


@Override 
public T getObject() throws Exception { 
    return Mockito.mock(classToBeMocked); 
} 

@Override 
public Class<?> getObjectType() { 
    return classToBeMocked; 
} 

@Override 
public boolean isSingleton() { 
    return true; 
} 
} 

Nella tua test-context.xml è necessario aggiungere le seguenti linee.

<bean id="serviceUtilMock" class="MockitoFactoryBean"> 
    <constructor-arg value="your.package.ServiceUtil" /> 
</bean> 

Se non si utilizza la configurazione XML, è necessario aggiungere l'equivalente di cui sopra nella configurazione di Java.

+0

Devo cambiare nulla alla classe che deve essere testato? Ho provato a creare un'istanza dell'oggetto ServiceUtils nella classe Test utilizzando questo factory ma il risultato è lo stesso @Mock 01Uutil utililt = factoryBean.getObject(); – Kaj

+0

Devi aggiungere FactoryBean nel tuo test-context.xml. Ho modificato la risposta. –