首页 > 解决方案 > 运行测试时在 Spring MvC 中注入 bean

问题描述

运行测试时出现此错误:

nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.bonanza.api.IWorkflowService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

这是我在运行类时加载的 servlet-xml:

  <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:jpa="http://www.springframework.org/schema/data/jpa"
            xmlns:util="http://www.springframework.org/schema/util"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xmlns:mvc="http://www.springframework.org/schema/mvc"
            xsi:schemaLocation="
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/data/jpa
            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config />
        <context:component-scan base-package="com.bonanza.*" />
        <jpa:repositories base-package="com.bonanza.*" />
        <!-- transaction management -->
        <mvc:annotation-driven />
    
        <bean id="workflowService"
                class="com.bonanza.api.IWorkflowService" abstract="true"/>
..
</beans>

标签: javaspringspring-mvcdependency-injectioninversion-of-control

解决方案


我认为您的问题是您正在尝试使用接口而不是具体类来注入com.bonanza.api.IWorkflowService应用程序中所需其他 bean 的类型的依赖关系。

为了解决这个问题,你有几个选择。

一方面,您当然可以为该接口提供实际的实现。

或者,另一方面,您可以为该接口提供一个模拟对象。您可以使用Mockito它,并使用类似于以下代码的内容修改您的 Spring XML 配置:

<beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:jpa="http://www.springframework.org/schema/data/jpa"
            xmlns:util="http://www.springframework.org/schema/util"
            xmlns:tx="http://www.springframework.org/schema/tx"
            xmlns:mvc="http://www.springframework.org/schema/mvc"
            xsi:schemaLocation="
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/data/jpa
            http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:annotation-config />
        <context:component-scan base-package="com.bonanza.*" />
        <jpa:repositories base-package="com.bonanza.*" />
        <!-- transaction management -->
        <mvc:annotation-driven />
    
        <bean id="workflowService" class="org.mockito.Mockito" factory-method="mock">
            <constructor-arg value="com.bonanza.api.IWorkflowService" />
        </bean>
..
</beans>

如果需要,您可以在配置中自定义模拟行为(来自您的其他问题):

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath:backoffice-servlet.xml")
public class TimeControllerTests {

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private IWorkflowService workflowService;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
        // given(this.workflowService...).willReturn(...);
    }
    
    @Test
    public void should_OK() throws Exception {

        mockMvc.perform(get("/time/2")
                .contentType(APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}

推荐阅读