8

使用 Spring 3.1.2、JUnit 4.10.0,这两个版本都相当新。我遇到了无法让基于注释的自动装配工作的问题。

下面是两个示例,一个没有使用注释,它工作正常。第二个使用注释,它不起作用,我找不到原因。我非常关注 spring-mvc-test 的示例。

工作

package com.company.web.api;
// imports

public class ApiTests {   

    @Test
    public void testApiGetUserById() throws Exception {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("/com/company/web/api/ApiTests-context.xml");
        UserManagementService userManagementService = (UserManagementService) ctx.getBean("userManagementService");
        ApiUserManagementController apiUserManagementController = new ApiUserManagementController(userManagementService);
        MockMvc mockMvc = standaloneSetup(apiUserManagementController).build();

        // The actual test     
        mockMvc.perform(get("/api/user/0").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
    }
}

失败,因为userManagementService为空,没有自动装配:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration       // should default to ApiTests-context.xml in same package
public class ApiTests {

    @Autowired
    UserManagementService userManagementService;

    private MockMvc mockMvc;

    @Before
    public void setup(){
        // SetUp never gets called?!
    }

    @Test
    public void testGetUserById() throws Exception {

        // !!! at this point, userManagementService is still null - why? !!!       

        ApiUserManagementController apiUserManagementController 
            = new ApiUserManagementController(userManagementService);

        mockMvc = standaloneSetup(apiUserManagementController).build();

        // The actual test
        mockMvc.perform(get("/api/user/0").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
    }
}

请注意,上面的两个测试类都应该使用相同的上下文配置,并且其中定义了 userManagementService。

ApiTests-context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=utf8"/>
        <property name="username" value="user"/>
        <property name="password" value="passwd"/>
    </bean>

    <!-- Hibernate SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
          p:dataSource-ref="dataSource" p:mappingResources="company.hbm.xml">
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
            </props>
        </property>
        <property name="eventListeners">
            <map>
                <entry key="merge">
                    <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
                </entry>
            </map>
        </property>
    </bean>

    <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
          p:sessionFactory-ref="sessionFactory"/>

    <!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= -->

    <context:annotation-config/>
    <tx:annotation-driven/>
    <context:mbean-export/>

    <!-- tried both this and context:component-scan -->
    <!--<bean id="userManagementService" class="com.company.web.hibernate.UserManagementServiceImpl"/>-->
    <context:component-scan base-package="com.company"/>

    <!-- Hibernate's JMX statistics service -->
    <bean name="application:type=HibernateStatistics" class="org.hibernate.jmx.StatisticsService" autowire="byName"/>

</beans>

并且 UserManagementService (接口)以及 UserManagementServiceImpl 具有@Service注释。

两个小问题/观察: setup() 永远不会被调用,即使它有 @Before 注释。此外,我注意到如果我的测试方法不以名称“test”开头,则它们不会被执行/识别,尽管我看到的所有 spring-mvc-test 示例都不是这种情况。

pom.xml:

    <dependency>
        <groupId>org.junit</groupId>
        <artifactId>com.springsource.org.junit</artifactId>
        <version>4.10.0</version>
        <scope>test</scope>
    </dependency>

在此处输入图像描述

更新:

仅当我从 Maven 运行测试时才会出现此问题;当我从我的 IDE (IntelliJ IDEA) 中运行测试时没关系。

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.12.3</version>
            <configuration>
                <includes>
                    <include>**/*Tests.java</include>
                </includes>
            </configuration>
        </plugin>
4

3 回答 3

6

除非您进行组件扫描,否则不会发生自动装配。

你为什么在你的代码中注释掉它?

<!--<context:component-scan base-package="com.company"/>-->

也回复:junit。如果您在 Eclipse 中,您可以转到 pom 的依赖树视图并在 junit 上进行过滤。检查您实际上使用的是该版本,而不是使用较旧的junit。

编辑:好的,我刚刚检查了您的配置,并且能够让它在这边工作。我唯一的猜测可能是您以某种方式使用糟糕的测试运行程序运行它,这导致它使用了错误的junit。

编辑2(已解决):所以事实证明问题是因为您使用的是自定义版本的junit。Surefire 寻找提供的 junit 库但找不到它。因此,它默认为 junit 3,这就是导致您的应用跳过加载配置的原因。

您可以明确指定自定义提供程序,例如

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.12.3</version>
    <dependencies>
      <dependency>
        <groupId>org.apache.maven.surefire</groupId>
        <artifactId>surefire-junit47</artifactId>
        <version>2.12.3</version>
      </dependency>
    </dependencies>
  </plugin>

但我发现它不适用于自定义回购。如果可能的话,我建议使用标准版本的 junit。

于 2012-09-21T12:46:54.477 回答
1

尝试特定的上下文配置,例如

@ContextConfiguration(locations = {"/file1.xml", "/file2.xml" })

(仅展示如何在需要时将其与多个文件一起使用 - 一个可能就足够了)

编辑:您是否启用了此处提到的 AutowiredAnnotationBeanPostProcessor?http://www.mkyong.com/spring/spring-auto-wiring-beans-with-autowired-annotation/

于 2012-09-21T11:37:43.790 回答
0

我有同样的问题。我的 @Autowire 可以在我的 IDE (SpringSource STS) 中工作,但是当我使用 Maven 从命令行构建时无法加载应用程序上下文。

问题在于我在 pom.xml 中的依赖项。我正在使用导致错误的 JUnit 的 Spring 版本。我认为这是原始帖子的根本原因。我不需要编写任何 Maven 插件就可以工作。

我变了

<dependency>
    <groupId>org.junit</groupId>
    <artifactId>com.springsource.org.junit</artifactId>
    <version>4.7.0</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
</dependency>
于 2013-03-12T20:37:38.857 回答