我正试图为这个Java SpringBoot的类写一个测试:
https://github.com/callistaenterprise/blog-microservices/blob/master/microservices/composite/product-composite-service/src/main/java/se/callista/microservices/composite/product/service/ProductCompositeIntegration.java
具体来说,我试图"模拟"这个方法调用:
URI uri = util.getServiceUrl("product");
我发现我应该"模拟"ServiceUtils
对象才能做到这一点。我尝试使用@Mock
和@InjectMocks
注释:
@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();
}
}
但是这样它仍然调用原来的ServiceUtils
对象,而不是"mock"对象。也尝试在ProductCompositeIntegration
上没有@Autowired
注释,但这导致NullPointerException
.
我做错了什么?
我的主类是这样的:
@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
public class ProductCompositeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductCompositeServiceApplication.class, args);
}
}
我试图模拟的ServiceUtils
对象在一个类中指定,用Spring的@Component
注释进行注释,以使用@Autowired
将其注入其他类。
经过反复试验,我终于解决了这个问题。
I drop the
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ProductCompositeServiceApplication.class)
测试类上面的注释。
我用@InjectMocks
标记了我正在测试的类,用@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...
}
}
我不确定这是否是最好的方法("Spring方式"),但这对我来说很有效。
这篇文章让我明白了:http://rdafbn.blogspot.be/2014/01/testing-spring-components-with-mockito.html
你必须写一个像
这样的FactoryBean
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;
}
}
在您的test-context.xml
中,您必须添加以下行:
<bean id="serviceUtilMock" class="MockitoFactoryBean">
<constructor-arg value="your.package.ServiceUtil" />
</bean>
如果不使用XML配置,则必须在Java配置中添加与上述相同的内容。