使用Spring Boot和Mockito进行模拟对象方法调用

时间:2015-09-28 10:14:42

标签: java spring unit-testing spring-boot mockito

我正在尝试为这个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对象,而不是“模拟”对象。还在@Autowired处没有ProductCompositeIntegration注释的情况下进行了尝试,但这会产生NullPointerException

我做错了什么?

我的主要课程如下:

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

我试图模拟的ServiceUtils对象在类中指定,使用Spring的@Component注释注释,使用@Autowired将其注入其他类。

2 个答案:

答案 0 :(得分:8)

经过大量的反复试验后,我设法解决了这个问题。

我放弃了

@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...
    }
}

我不确定这是否是最好的方法(“春天的方式”),但这对我有用。

这篇文章让我很清楚:http://rdafbn.blogspot.be/2014/01/testing-spring-components-with-mockito.html

答案 1 :(得分:0)

你必须写一个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配置中添加上述等效项。