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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32820546/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 20:49:30  来源:igfitidea点击:

Mock object method call using Spring Boot and Mockito

javaspringunit-testingspring-bootmockito

提问by Kaj

I am trying to write a test for this Java SpringBoot's class:

我正在尝试为此 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

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

Specifically, I am trying to "mock" this method call:

具体来说,我试图“模拟”这个方法调用:

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

I figured out I should "mock" the ServiceUtilsobject in order to do this. I tried this using the @Mockand @InjectMocksannotations:

我想我应该“模拟”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();
    }
}

But this way it still calls the original ServiceUtilsobject, and not the "mocked" one. Also tried without the @Autowiredannotation at the ProductCompositeIntegration, but this results in a NullPointerException.

但是这样它仍然调用原始ServiceUtils对象,而不是“模拟”对象。也尝试在 没有@Autowired注释的情况下ProductCompositeIntegration,但这会导致NullPointerException.

What am I doing wrong?

我究竟做错了什么?



My main class looks like this:

我的主要课程是这样的:

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

The ServiceUtilsobject that I am trying to mock is specified in a class, annotated with Spring's @Componentannotation to inject it into the other classes using @Autowired.

ServiceUtils我试图模拟的对象在一个类中指定,用 Spring 的@Component注释进行注释,以使用@Autowired.

采纳答案by Kaj

After a lot of trial and error I managed to solve this problem.

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

I dropped the

我放弃了

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

annotations aboved the test class.

测试类上方的注释。

I marked the class that I was testing with @InjectMocksand the dependencies with @Mock:

我标记了我正在测试的类@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...
    }
}

I'm not sure if this is the best approach ("the Spring way"), but this worked for me.

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

This article made it all clear to me: http://rdafbn.blogspot.be/2014/01/testing-spring-components-with-mockito.html

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

回答by Sandra Parsick

You have to write a FactoryBeanlike

你得写个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;
 }
}

In your test-context.xmlyou have to add the following lines.

在您test-context.xml必须添加以下行。

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

If you don't use XML configuration, then you have to add the equivalent to above in your Java configuration.

如果您不使用 XML 配置,则必须在 Java 配置中添加与上述等效的内容。