【问题标题】:Mock object method call using Spring Boot and Mockito使用 Spring Boot 和 Mockito 模拟对象方法调用
【发布时间】:2015-12-25 13:13:12
【问题描述】:

我正在尝试为这个 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 对象,而不是“模拟”对象。还尝试在ProductCompositeIntegration 处不使用@Autowired 注释,但这会导致NullPointerException

我做错了什么?


我的主课是这样的:

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

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

【问题讨论】:

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


    【解决方案1】:

    你必须写一个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 配置中添加上面的等价物。

    【讨论】:

    • 我必须对必须测试的类进行任何更改吗?我尝试使用这个工厂在 Test 类中实例化 ServiceUtils 对象,但结果是相同的 @Mock private ServiceUtils util = factoryBean.getObject();
    • 您必须在 test-context.xml 中添加 FactoryBean。我编辑了答案。
    【解决方案2】:

    经过多次反复试验,我设法解决了这个问题。

    我放弃了

    @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

    【讨论】:

    • 我喜欢你的方法。这正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    • 2021-11-26
    • 2019-11-19
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多