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
How to autowire field in static @BeforeClass?
提问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 ,您所要做的就是:
Declare your test class with
@ExtendWith(SpringExtension.class)Inject your
@BeforeAll(replacement for@BeforeClassin JUnit 5) with the bean
声明你的测试类
@ExtendWith(SpringExtension.class)使用 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);进行一些初始化。方法,因此您不依赖于您还必须单独测试的类/方法。

