Pregunta

I am playing around with a Spring MVC + Hibernate + MySQL "Hello World" app, and am currently trying run the following integration test on a Spring MVC controller using jUnit.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file:src/main/webapp/WEB-INF/springapp-servlet.xml"})
public class InventoryControllerIT
{
    @Autowired
    private InventoryController controller;

    @Test
    public void handleRequest_anyRequest_returnsSuccessfully() throws Exception
    {       
        ModelAndView modelAndView = this.controller.handleRequest(null, null);
    }
}

However, every time I do so I get the following exception:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [springapp.web.InventoryController] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.

Previously I hadn't implemented any real data access and the test passed fine, but now that I have added a Hibernate implementation of my DAO along with spring transaction management I get this error. Here are the relevant parts of my applet context configuration 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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/tx
                           http://www.springframework.org/schema/tx/spring-tx.xsd">


    <bean name="/hello.htm" class="springapp.web.InventoryController">
        <property name="productManager" ref="productManager" />
        <property name="productDao" ref="productDao" />
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>


    ...


    <!-- Hibernate -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

        <property name="dataSource">
            <ref bean="dataSource" />
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>

        <property name="mappingJarLocations">
            <list>
                <value>WEB-INF/lib/springapp-dataaccess*.jar</value>
            </list>
        </property>
    </bean>

    <bean id="productDao" class="springapp.dataaccess.dao.ProductHibernateDao">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven />

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager"
        p:sessionFactory-ref="sessionFactory" />

</beans>

If I remove the <tx:annotation-driven /> from the config then the above exception does not occur, but then the test fails because the data access call that occurs in the handler no longer has an open transaction. The app runs just fine outside of the test. Anyone have any ideas as to what the issue is?

¿Fue útil?

Solución

When InventoryController implements any interfaces Spring by default applies transactional aspect to it using interface-based proxy. Such a proxy implements interfaces of InventoryController, but it's not a subclass of InventoryController, therefore it cannot be injected into a field of type InventoryController.

You either need to use interface as a type of the field to be autowired, or configure Spring to apply target-class-based proxy instead.

See also:

Otros consejos

I had a similar issues while running the unit tests of a small library I was building.

replace your :

<tx:annotation-driven />

with

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

Note that on my project I also had to add the following dependency (maven project) for the unit tests:

    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.2.2</version>
        <scope>test</scope>
    </dependency>

Best regards.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top