java 单元测试时如何使用AnnotationConfigWebApplicationContext(Spring框架)加载配置类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4154155/
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-10-30 05:04:24  来源:igfitidea点击:

How to use AnnotationConfigWebApplicationContext (Spring framework) to load configuration class during unit test

javaspringconfigurationjunit

提问by charles

I use Spring framework 3.0.5 to build a web application. I use @Configuration annotation to configure my domain object, and some of the domain objects are with session scope. And when I write a unit test using jUnit 4.8.2, the AnnotationConfigWebApplicationContextvariable cannot get the beans which are defined in configuration class.

我使用 Spring 框架 3.0.5 来构建一个 Web 应用程序。我使用@Configuration 注释来配置我的域对象,并且一些域对象具有会话范围。当我使用 jUnit 4.8.2 编写单元测试时,该AnnotationConfigWebApplicationContext变量无法获取配置类中定义的 bean。

I always get the following exceptions:

我总是得到以下例外:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'country' is defined

Is there anyone who can give me some advice for this problem? Thanks a lot!

有没有人可以就这个问题给我一些建议?非常感谢!

Here is my configuration class, unit test class, DAO class and domain object class. (I use annotation to configure the app instead of xml)

这是我的配置类、单元测试类、DAO 类和域对象类。(我使用注解来配置应用程序而不是 xml)

Configuration class:

配置类:

@Configuration
public class RegionDomainObj
{

 /**
  *  Define City Domain Object bean
  */
 @Bean
 @Scope("session")
 public CityImp city()
 {
  return new CityImp();
 }

 /**
  *  Define City IP Domain Object bean
  */
 @Bean
 @Scope("session")
 public CityIPImp cityIP()
 {
  return new CityIPImp();
 }

 /**
  *  Define Country Domain Object bean
  */
 @Bean
 @Scope("session")
 public CountryImp country()
 {
  return new CountryImp();
 }

 /**
  *  Define Country IP Domain Object bean
  */
 @Bean
 @Scope("session")
 public CountryIPImp countryIP()
 {
  return new CountryIPImp();
 }

 /**
  *  Define Locale Domain Object bean
  */
 @Bean
 @Scope("session")
 public LocaleImp locale()
 {
  return new LocaleImp();
 }

 /**
  *  Define Region Domain Object bean
  */
 @Bean
 @Scope("session")
 public RegionImp region()
 {
  return new RegionImp();
 }

 /**
  *  Define Top Level Domain Domain Object bean
  */
 @Bean
 @Scope("session")
 public TopLevelDomainImp topLevelDomain()
 {
  return new TopLevelDomainImp();
 }
}

Test super class:

测试超类:

@RunWith(SpringJUnit4ClassRunner.class)
public class TestENV 
{
 protected AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext;

 @Before
 public void setUp()
 {
  annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
  annotationConfigWebApplicationContext.refresh();
 }
}

Unit Test class:

单元测试类:

public class CountryDAOTest extends TestENV
{

 private ICountryDAO countryDAO; 

 private ICountry country;

 @Before
 public void setUpLocalTestENV()
 {
  this.country = (ICountry) this.annotationConfigWebApplicationContext.getBean("country");
  this.countryDAO = (ICountryDAO) this.annotationConfigWebApplicationContext.getBean("crazyamsCountryDAO");
 }

 /* Test save country */
 @Test
 public void testSaveCountry()
 {
   this.country.setCode("AU");
   this.country.setName("Australia");
   this.countryDAO.save(this.country);
         /* ignore the assert functions */
 }
}

Update

更新

Maybe I make this problem too complex, you know, when we use AnnotationConfigApplicationContext, we can use the following code to register bean definitions.

可能是我把这个问题说的太复杂了,你知道的,我们在使用的时候AnnotationConfigApplicationContext,可以用下面的代码来注册bean定义。

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();

annotationConfigApplicationContext.register(TestProcessUnitConfig.class, OtherClazz.class);

And in my project, I use Spring MVC with annotation support, and I use AnnotationConfigWebApplicationContextinstead of AnnotationConfigApplicationContext.

而在我的项目,我用Spring MVC的注解与支持,我用AnnotationConfigWebApplicationContext的不是AnnotationConfigApplicationContext

Although they are very similar, AnnotationConfigWebApplicationContextdoesn't provide "register" function.

虽然它们非常相似,AnnotationConfigWebApplicationContext但不提供“注册”功能。

And I just want to know whether there is another way to register bean definition into AnnotationConfigWebApplicationContextor not.

我只想知道是否有另一种方法可以将 bean 定义注册到其中AnnotationConfigWebApplicationContext

回答by Christian Spiller

I think you need to use your @Configuration class in the context constructor:

我认为您需要在上下文构造函数中使用 @Configuration 类:

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(RegionDomainObj.class);

or with register:

或注册:

AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.register(RegionDomainObj.class);

As far as I know, AnnotationConfigWebApplicationContext(with the 'Web') is for JSF things.

据我所知,AnnotationConfigWebApplicationContext(带有“Web”)是针对 JSF 的。

回答by Sobik

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named

org.springframework.beans.factory.NoSuchBeanDefinitionException:没有命名的bean

This error appears when something wrong with your configuration classes. In your case you have to directly define where you beans defined. So, add next codelines after @Configurationin your test class:

当您的配置类出现问题时会出现此错误。在您的情况下,您必须直接定义 bean 定义的位置。因此,@Configuration在您的测试类之后添加下一个代码行:

@WebAppConfiguration
@ContextConfiguration(classes={/*..your configuration classes*/})
@PropertySource(/*.. your possible properties files..*/);

回答by Sean Patrick Floyd

I don't know if that's the cause but there is one thing that bothers me:

我不知道这是否是原因,但有一件事情困扰着我:

Your exporting countryas an implementation class:

您导出country为实现类:

 /**
  * Define Country Domain Object bean
  */
 @Bean @Scope("session") public CountryImp country(){
     return new CountryImp();
 }

But reference it as an interface:

但将其作为接口引用:

this.country = (ICountry) this.annotationConfigWebApplicationContext.getBean("country");

The more obvious way would be to export it as interface as well:

更明显的方法是将其导出为接口:

 /**
  * Define Country Domain Object bean
  */
 @Bean @Scope("session") public ICountry country(){
     return new CountryImp();
 }

Try and see if that makes a difference. Even if it doesn't, it improves your code.

尝试看看这是否有所作为。即使没有,它也会改进您的代码。