Spring Junit 测试自动装配失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10608967/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:07:23  来源:igfitidea点击:

Autowired Fails with Spring Junit Test

springjunit4spring-test

提问by IcedDante

Writing Junit Tests for my spring application. Because I am new at this I tried starting off by writing a Unit Test for a DAO class that I know works (ran it in JBoss). However, I cannot get it to work as a Unit Test in Eclipse. I keep getting an "Error creating bean... Could not autowire field: NoSuchBeanDefinition".

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

I saw errors similar to this on StackOverflow and other sites and it always ended up being a syntax error or attempting to autowire the Implementation of the interface as opposed to the Interface, etc. I don't see any of those errors with my code.

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

I did download Spring-test.jar separately from the Spring configuration that came with the project. Both are from Spring 2.5 however, so I don't think that should be an issue :/

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

Eclipse comes bundled with JUnit 4.8 and Spring Unit Test doesn't work with that so I downgraded my JUnit to use 4.4

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

One thing to consider... if you look at the code for my Unit Test you will notice that I autowire two fields: a SimpleJdbcTemplate at the Query Service I want to test. Well if I remove the DrugDao and all references to it, then the SimpleJdbcQuery auto-wires just fine.

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

Here is the stacktrace for your review:

这是您审核的堆栈跟踪:

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.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

Here is the Interface and Implementation:

下面是接口和实现:

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

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 (located in a separate source folder at first, then tried it in the same folder)

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

<?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>

采纳答案by IcedDante

My mistake: there was another Spring Configuration file referenced elsewhere that I missed. Adding this field and defining setters in my Unit Test for any autowired fields solved the problem.

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

I am using this checklist now when these types of errors occur:

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

  • Make sure that implementing class of Interface type uses “@Service” annotation
  • Make sure beans are configured properly in the XML:
  • Simplest way is to use:
  • 确保接口类型的实现类使用“@Service”注解
  • 确保在 XML 中正确配置了 bean:
  • 最简单的方法是使用:

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

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

  • This adds all classes under the package name
  • Or create XML Bean Definitions
  • 这将添加包名称下的所有类
  • 或者创建 XML Bean 定义

回答by vshank77

I had the similar issue and found that while I could AutoWire classes successfully in Eclipse, surefire required only interfaces to be AutoWired. Especially this occurs only when using Cobertura for instrumenting, so pretty sure there is something wrong with the proxy generation. For now, I have just introduced a new interface as it was appropriate for my use-case but there should definitely be another appropriate solution.

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

回答by Jose Luis Martin

Add a bean definition of type SpringJdbcDrugQueryto common-test.xml

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

回答by Longli

I encounter this problem too, and I just add setter, then it works well.

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