4

为我的 spring 应用程序编写 Junit 测试。因为我是新手,所以我尝试从为我知道有效的 DAO 类编写单元测试开始(在 JBoss 中运行它)。但是,我无法让它在 Eclipse 中作为单元测试工作。我不断收到“创建 bean 时出错...无法自动装配字段:NoSuchBeanDefinition”

我在 StackOverflow 和其他网站上看到了与此类似的错误,它总是以语法错误或试图自动装配接口的实现而不是接口等而告终。我的代码没有看到任何这些错误。

我确实从项目附带的 Spring 配置中单独下载了 Spring-test.jar。然而,两者都来自 Spring 2.5,所以我认为这不应该是一个问题:/

Eclipse 与 JUnit 4.8 捆绑在一起,而 Spring Unit Test 无法使用它,因此我将 JUnit 降级为使用 4.4

需要考虑的一件事...如果您查看我的单元测试的代码,您会注意到我自动装配了两个字段:一个 SimpleJdbcTemplate 在我要测试的查询服务中。好吧,如果我删除 DrugDao 和对它的所有引用,那么 SimpleJdbcQuery 自动连接就好了。

这是供您查看的堆栈跟踪:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tst.hcps.glucosemanagement.dataaccess.DrugDaoTest': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.hcps.glucosemanagement.repository.meds.DrugDao tst.hcps.glucosemanagement.dataaccess.DrugDaoTest.dQuery; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.hcps.glucosemanagement.repository.meds.DrugDao] is defined: Unsatisfied dependency of type [interface com.hcps.glucosemanagement.repository.meds.DrugDao]: expected at least 1 matching bean
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:243)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:329)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:127)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:85)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:95)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:139)
    at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
    at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
    at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.hcps.glucosemanagement.repository.meds.DrugDao tst.hcps.glucosemanagement.dataaccess.DrugDaoTest.dQuery; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.hcps.glucosemanagement.repository.meds.DrugDao] is defined: Unsatisfied dependency of type [interface com.hcps.glucosemanagement.repository.meds.DrugDao]: expected at least 1 matching bean
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:435)
    at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:240)
    ... 18 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.hcps.glucosemanagement.repository.meds.DrugDao] is defined: Unsatisfied dependency of type [interface com.hcps.glucosemanagement.repository.meds.DrugDao]: expected at least 1 matching bean
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:613)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:412)
    ... 20 more

这是接口和实现:

DrugDao.java

package com.hcps.glucosemanagement.repository.meds;

import java.util.List;

import com.hcps.glucosemanagement.domain.meds.Drug;

public interface DrugDao {

    public List<Drug> searchDrugsByPrimaryName(String facilityId, String name);

    public List<Drug> searchDrugs(String facilityId, String primaryName, String secondaryName);

}

SpringJdbcDrugQuery.java

package com.hcps.glucosemanagement.repository.meds;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.stereotype.Service;

import com.hcps.glucosemanagement.domain.meds.Drug;
import com.hcps.glucosemanagement.repository.DaoOperations;

@Service
public class SpringJdbcDrugQuery extends DaoOperations implements DrugDao {

private static final Logger logger = Logger.getLogger(SpringJdbcDrugQuery.class);

public List<Drug> searchDrugsByPrimaryName(String facilityId, String name) 
{
    return searchDrugs(facilityId, name, null);
}

public List<Drug> searchDrugs(String facilityId, String primaryName, String secondaryName) 
{
    List<Drug> results = null;

    StringBuffer sql = new StringBuffer();    
    HashMap<String, Object> namedParameters = new HashMap<String, Object>();

    if(primaryName==null) return null;

    sql = new StringBuffer();

    sql.append("SELECT");
            ...
        results = simpleJdbcTemplate.query(sql.toString(), new DrugMapper(), 


    return results;
}

private static final class DrugMapper implements ParameterizedRowMapper<Drug> 
{

    public Drug mapRow(ResultSet rs, int rowNum) throws SQLException {
        Drug drug = new Drug();
        drug.setFacilityId(rs.getString("FACILITY_ID"));
        drug.setPrimaryName(rs.getString("PRIMARY_NAME"));
        drug.setSecondaryName(rs.getString("SEC_NAME"));
        return drug;
    }

}
}

DrugDaoTest2.java (最初位于单独的源文件夹中,然后在同一文件夹中尝试)

package com.hcps.glucosemanagement.repository.meds;

import static org.junit.Assert.assertTrue;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.hcps.glucosemanagement.domain.meds.Drug;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
        "classpath:common-test.xml"
})
public class DrugDaoTest2 {

    @Autowired
    DrugDao dQuery;
    @Autowired
    SimpleJdbcTemplate queryTemplate;

    @Test public void glucoseFetch() {
        List<Drug> rslts = dQuery.searchDrugsByPrimaryName(null, "INSU*");
        assertTrue(rslts.size()>0);
        int i=0;
        System.out.println(i);

    }

    public void setDrugDao(DrugDao drugDao) {
        this.dQuery = drugDao;
    }
}

common-test.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"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
>

   <!--
   Test configuration for Spring/JUnit Testing
   -->

  <bean id="contextApplicationContextProvider" class="com.hcps.glucosemanagement.spring.ApplicationContextProvider" />

  <bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="beans">
      <map>
        <entry key="bean:name=Log4jJmxServiceMBean" value-ref="glucosemanagement.Log4jJmxService" />
      </map>
    </property>
  </bean>
  <bean id="glucosemanagement.Log4jJmxService" class="com.hcps.glucosemanagement.logging.Log4jJmxService" />

  <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="/WEB-INF/messages" />
  </bean>

  <bean id="parameterMappingInterceptor" class="org.springframework.web.portlet.handler.ParameterMappingInterceptor" />
  <bean id="viewResolverCommon" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    p:order="2"
    p:cache="false"
    p:viewClass="org.springframework.web.servlet.view.JstlView"
    p:prefix="/WEB-INF/jsp/"
    p:suffix=".jsp"
  />

  <bean id="defaultExceptionHandler" class="org.springframework.web.portlet.handler.SimpleMappingExceptionResolver">
    <property name="defaultErrorView" value="../error"/>
    <property name="exceptionMappings">
      <props>
        <prop key="javax.portlet.PortletSecurityException">notAuthorized</prop>
        <prop key="javax.portlet.UnavailableException">notAvailable</prop>
      </props>
    </property>
  </bean>

  <bean id="simpleParameterJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
    <constructor-arg ref="hciDataSource" />
  </bean>

  <bean id="hciDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url" value="jdbc:oracle:thin:@//vir-tst.com:1521/qar01.world" />
    <property name="username" value="ccuser" />
    <property name="password" value="bueno" />
    <property name="maxActive" value="30" />
    <property name="maxWait" value="30" />
    <property name="maxIdle" value="30" />
  </bean>

</beans>
4

4 回答 4

4

我的错误:我错过了在其他地方引用的另一个 Spring 配置文件。在我的单元测试中为任何自动装配的字段添加此字段并定义设置器解决了这个问题。

当发生这些类型的错误时,我现在正在使用此清单:

  • 确保接口类型的实现类使用“@Service”注解
  • 确保在 XML 中正确配置 bean:
  • 最简单的方法是使用:

<context:component-scan base-package="com.customization.packagename" />

  • 这会添加包名下的所有类
  • 或者创建 XML Bean 定义
于 2012-05-16T17:20:36.437 回答
1

我遇到了类似的问题,发现虽然我可以在 Eclipse 中成功地 AutoWire 类,但 Surefire 只需要 AutoWired 接口。尤其是仅在使用 Cobertura 进行检测时才会发生这种情况,因此可以肯定代理生成存在问题。现在,我刚刚介绍了一个新界面,因为它适合我的用例,但肯定应该有另一个合适的解决方案。

于 2013-07-12T11:32:06.953 回答
0

将类型的 bean 定义添加SpringJdbcDrugQuery到 common-test.xml

于 2012-05-15T22:29:46.100 回答
-1

我也遇到这个问题,我只是添加了setter,然后效果很好。

于 2012-08-17T03:09:21.247 回答