简体   繁体   English

SpringBeanAutowiringSupport 不在 jUnit 测试中注入 beans

[英]SpringBeanAutowiringSupport does not inject beans in jUnit tests

I use SpringBeanAutowiringSupport for bean injection in some objects.我使用SpringBeanAutowiringSupport在某些对象中进行 bean 注入。 Problem is, that injection of beans does not work in jUnit tests.问题是,bean 注入在 jUnit 测试中不起作用。 For testing is used SpringJUnit4ClassRunner.用于测试的是 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());
        // ...
    }
  // ...
}

Does anyone have any idea, why injection using SpringBeanAutowiringSupport does not work in jUnit tests?有谁知道,为什么使用SpringBeanAutowiringSupport的注入在 jUnit 测试中不起作用?

well spring + junit team have already fixed this . spring + junit 团队已经解决了这个问题。 look this link -- >看这个链接-->
spring unit testing 弹簧单元测试

otherwise you can call the spring context and use the getBean method , but in that way you can even do it with a simple main test inside your class instead of junit test否则你可以调用 spring 上下文并使用 getBean 方法,但这样你甚至可以在你的类中使用一个简单的主测试而不是 junit 测试来完成

**note if you use the spring + junit config you have to put the test-spring-context.xml into the test package **注意,如果您使用 spring + junit 配置,则必须将 test-spring-context.xml 放入测试包中

Thanks to M. Denium's, his solution workds.感谢 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());
            // ...
        }
      // ...
    }

I made my own version that supports passing in an ApplicationContext not just limited to WebApplicationContext .我制作了自己的版本,它支持传入ApplicationContext而不仅仅是WebApplicationContext This will allow it to work in both test and normal context.这将允许它在测试和正常环境中工作。

/**
 * 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();

    }
}

To make it easier to use on tests, I add a TestExecutionListener为了更容易在测试中使用,我添加了一个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());
    }
}

Then use it in my tests with然后在我的测试中使用它

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM