java 如何在静态@BeforeClass 中自动装配字段?

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

How to autowire field in static @BeforeClass?

javaspringjunitspring-test

提问by membersound

@RunWith(SpringJUnit4ClassRunner.class)
public void ITest {
    @Autowired
    private EntityRepository dao;

    @BeforeClass
    public static void init() {
        dao.save(initialEntity); //not possible as field is not static
    }
}

How can I have my service injected already in the static init class?

如何将我的服务注入到静态 init 类中?

采纳答案by Nenad Bozic

It looks to me that you are trying to populate DB before tests.

在我看来,您正在尝试在测试之前填充数据库。

I would give a try to two options:

我会尝试两种选择:

  • If you can extract initial scripts to sql file (if that is option for you without using repository bean) you can use this approachand annotate your test with @Sql
  • You can explore DbUnitand here is link to spring dbunit connectorwhich is doing exactly that and helping you populate DB before tests. Here is a github linkfor integrating between spring test framework and dbunit. After you do that you have @DatabaseSetupand @DatabaseTearDownwhich will do thing on DB you need
  • 如果您可以将初始脚本提取到 sql 文件(如果您可以选择不使用存储库 bean),则可以使用此方法并使用@Sql
  • 您可以探索DbUnit,这里是spring dbunit 连接器的链接,它正是这样做的,并帮助您在测试前填充数据库。这是一个用于在 spring 测试框架和 dbunit 之间集成的github 链接。当你做,你必须@DatabaseSetup@DatabaseTearDown将做的事情DB你需要

I know that this does not answer how to inject bean in static @BeforeClassbut form code it looks it is solving your problem.

我知道这并没有回答如何在静态中注入 bean,@BeforeClass但它看起来正在解决您的问题的表单代码。

Update:I recently run into same problem in my project and dug out this articlewhich helped me and I think it is elegant way of dealing with this type of problem. You can extend SpringJUnit4ClassRunnerwith listener which can do instance level setup with all your defined beans.

更新:我最近在我的项目中遇到了同样的问题,并挖出了这篇对我有帮助的文章,我认为这是处理此类问题的优雅方式。您可以SpringJUnit4ClassRunner使用监听器进行扩展,它可以使用您定义的所有 bean 进行实例级设置。

回答by Narain Mittal

One workaround that I have been using to get this working is to use @Beforewith a flag to skip it being executed for each testcase

我一直在使用的一种解决方法是使用@Before一个标志来跳过它为每个测试用例执行

@RunWith(SpringJUnit4ClassRunner.class)
public class BaseTest {

@Autowired
private Service1 service1;

@Autowired
private Service2 service2;

private static boolean dataLoaded = false;

@Before
public void setUp() throws Exception {

    if (!dataLoaded) {
        service1.something();
        service2.somethingElse();
        dataLoaded = true;
    }
  }
}

回答by Vladtn

With Junit 5 you can do this (@BeforeAll instead of @BeforeClass)

使用 Junit 5 你可以做到这一点(@BeforeAll 而不是 @BeforeClass)

public void ITest {
    @Autowired
    private EntityRepository dao;

    @BeforeAll
    public static void init(@Autowired EntityRepository dao) {
        dao.save(initialEntity); //possible now as autowired function parameter is used
    }
}

By leaving the field it means it can be used in other tests

离开该领域意味着它可以用于其他测试

回答by yeralin

UPD for Spring 2.x versions.

Spring 2.x 版本的 UPD。

Spring 2.x supports new feature a SpringExtensionfor Junit 5 Jupiter, where all you have to do is:

Spring 2.x 支持SpringExtensionJunit 5 Jupiter 的新特性 a ,您所要做的就是:

  1. Declare your test class with @ExtendWith(SpringExtension.class)

  2. Inject your @BeforeAll(replacement for @BeforeClassin JUnit 5) with the bean

  1. 声明你的测试类 @ExtendWith(SpringExtension.class)

  2. 使用 bean注入您的@BeforeAll(替代@BeforeClassJUnit 5 中的)

For example:

例如:

@ExtendWith(SpringExtension.class)
...
public void ITest {

    @BeforeAll
    public static void init(@Autowired EntityRepository dao) {
        dao.save(initialEntity);
    }

}

Assuming you correctly configured JUnit 5 Jupiter with Spring 2.x

假设您使用 Spring 2.x 正确配置了 JUnit 5 Jupiter

More about it here: https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-junit-jupiter-extension

更多关于它的信息:https: //docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-junit-jupiter-extension

回答by musikele

To answer this question we should recap Spring 2.x versions.

要回答这个问题,我们应该回顾一下 Spring 2.x 版本。

If you want to "autowire" a bean in your @BeforeTestclass you can use the ApplicationContextinterface. Let's see an example:

如果你想在你的@BeforeTest类中“自动装配”一个 bean,你可以使用该ApplicationContext接口。让我们看一个例子:

@BeforeClass
    public static void init() {
        ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
        EntityRepository dao2 = (EntityRepository) context.getBean("dao");
        List<EntityRepository> all = dao2.getAll();
        Assert.assertNotNull(all);
    }

What's happening: using the ClassPathXmlApplicationContextwe are instantiating all beans contained in the application-context.xmlfile.

发生了什么:使用ClassPathXmlApplicationContext我们正在实例化application-context.xml文件中包含的所有 bean 。

With context.getBean()we read the bean specified (it must match the name of the bean!); and then you can use it for your initialization.

随着context.getBean()我们读指定的豆(必须bean的名称相匹配!); 然后您可以将其用于初始化。

You should give to the bean another name (that's the dao2!) otherwise Spring normal "autowired" cannot work on the predefined bean.

你应该给 bean 另一个名字(那就是dao2!)否则 Spring 正常的“自动装配”不能在预定义的 bean 上工作。

As a side note, if your test extends AbstractTransactionalJUnit4SpringContextTestsyou can do some initialization using executeSqlScript(sqlResourcePath, continueOnError); method, so you don't depend on a class/method that you also have to test separately.

作为旁注,如果您的测试扩展,AbstractTransactionalJUnit4SpringContextTests您可以使用executeSqlScript(sqlResourcePath, continueOnError);进行一些初始化。方法,因此您不依赖于您还必须单独测试的类/方法。