【问题标题】:SpringBeanAutowiringSupport does not inject beans in jUnit testsSpringBeanAutowiringSupport 不在 jUnit 测试中注入 bean
【发布时间】:2014-09-18 21:49:49
【问题描述】:

我在某些对象中使​​用SpringBeanAutowiringSupport 进行 bean 注入。问题是,bean 的注入在 jUnit 测试中不起作用。用于测试使用 SpringJUnit4ClassRunner。

public class DossierReportItemXlsImporterImpl implements DossierRerportItemXlsImporer {

    private final Logger logger = Logger.getLogger(getClass());
    // are not autowired.
    @Autowired
    private DossierReportService dossierReportService;
    @Autowired
    private DossierReportItemService dossierReportItemService;
    @Autowired
    private NandoCodeService nandoCodeService;

    public DossierReportItemXlsImporterImpl(){
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    //...
}


public class DossierRerportItemXlsImporerTest extends AuditorServiceTest{

    // injected OK
    @Autowired
    private DossierReportService dossierReportService;
    @Autowired
    private DossierReportItemService dossierReportItemService;

    @Test
    public void testXlsImport(){
        DossierRerportItemXlsImporer importer = new DossierReportItemXlsImporterImpl();
        importer.processImport(createDossierReport(), loadFile());
        // ...
    }
  // ...
}

有谁知道,为什么使用SpringBeanAutowiringSupport 进行注入在 jUnit 测试中不起作用?

【问题讨论】:

  • 因为测试运行器不使用ContextLoader 来加载上下文。这由SpringBeanAutowiringSupport 使用。它基本上不检测上下文。作为一个额外的困难,它还期望它是WebApplicationContext,而不是常规的ApplicationContext。作为一种解决方法,您可以注入ApplicationContext 并通过调用getAutowireCapableBeanFactory().autowireBean(yourInstance); 自己手动进行接线。

标签: java spring junit


【解决方案1】:

spring + junit 团队已经解决了这个问题。看这个链接 -->
spring unit testing

否则你可以调用 spring 上下文并使用 getBean 方法,但这样你甚至可以在你的类中使用一个简单的主测试来代替 junit 测试

**注意如果你使用 spring + junit 配置你必须把 test-spring-context.xml 放到测试包中

【讨论】:

    【解决方案2】:

    感谢 M. Denium,他的解决方案奏效了。

    public class DossierReportItemXlsImporterImpl implements DossierRerportItemXlsImporer {
    
        private final Logger logger = Logger.getLogger(getClass());
    
        @Autowired
        private DossierReportService dossierReportService;
        @Autowired
        private DossierReportItemService dossierReportItemService;
        @Autowired
        private NandoCodeService nandoCodeService;
    
        public DossierReportItemXlsImporterImpl(final ApplicationContext contex){
            contex.getAutowireCapableBeanFactory().autowireBean(this);
        }
    
        //...
    }
    
    
     public class DossierRerportItemXlsImporerTest extends AuditorServiceTest{
    
            @Autowired
            private ApplicationContext context;
            @Autowired
            private DossierReportService dossierReportService;
            @Autowired
            private DossierReportItemService dossierReportItemService;
    
            @Test
            public void testXlsImport(){
                DossierRerportItemXlsImporer importer = new DossierReportItemXlsImporterImpl(context);
                importer.processImport(createDossierReport(), loadFile());
                // ...
            }
          // ...
        }
    

    【讨论】:

      【解决方案3】:

      我制作了自己的版本,支持传入ApplicationContext,而不仅限于WebApplicationContext。这将允许它在测试和正常环境中工作。

      /**
       * This is an implementation of {@link org.springframework.web.context.support.SpringBeanAutowiringSupport} that
       * has a fallback that can be used in unit tests.
       */
      public final class SpringBeanAutowiringSupport {
          private static final ThreadLocal<ApplicationContext> applicationContextThreadLocal = new ThreadLocal<>();
      
          private SpringBeanAutowiringSupport() {}
      
          public static void setApplicationContext(final ApplicationContext applicationContext) {
      
              applicationContextThreadLocal.set(applicationContext);
          }
      
          public static void processInjectionBasedOnCurrentContext(Object target) {
      
              var cc = ContextLoader.getCurrentWebApplicationContext();
              if (cc != null) {
                  org.springframework.web.context.support.SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(target);
              } else if (applicationContextThreadLocal.get() != null) {
                  AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
                  bpp.setBeanFactory(applicationContextThreadLocal.get().getAutowireCapableBeanFactory());
                  bpp.processInjection(target);
              }
      
          }
      
          public static void unload() {
      
              applicationContextThreadLocal.remove();
      
          }
      }
      

      为了在测试中更容易使用,我添加了TestExecutionListener

      public class SpringBeanAutowiringSupportTestExecutionListener extends AbstractTestExecutionListener {
      
          @Override
          public void afterTestMethod(final TestContext testContext) {
      
              SpringBeanAutowiringSupport.unload();
      
          }
      
          @Override
          public void beforeTestMethod(final TestContext testContext) {
      
              SpringBeanAutowiringSupport.setApplicationContext(testContext.getApplicationContext());
          }
      }
      

      然后在我的测试中使用它

      @RunWith(SpringRunner.class)
      @TestExecutionListeners(listeners = {SpringBeanAutowiringSupportTestExecutionListener.class}, mergeMode = MERGE_WITH_DEFAULTS)
      public class MyTest {
      ...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-28
        • 2015-08-08
        • 1970-01-01
        • 2018-05-15
        • 1970-01-01
        • 2020-01-17
        • 2019-06-04
        • 1970-01-01
        相关资源
        最近更新 更多