是否有任何最佳实践让Junit在测试文件中执行一次功能,并且它也不应该是静态的。
像@BeforeClass
非静态功能?
这是一个丑陋的解决方案:
@Before void init(){
if (init.get() == false){
init.set(true);
// do once block
}
}
好吧,这是我不想做的事情,我正在寻找集成的junit解决方案。
是否有任何最佳实践让Junit在测试文件中执行一次功能,并且它也不应该是静态的。
像@BeforeClass
非静态功能?
这是一个丑陋的解决方案:
@Before void init(){
if (init.get() == false){
init.set(true);
// do once block
}
}
好吧,这是我不想做的事情,我正在寻找集成的junit解决方案。
Answers:
如果您不想为一次初始化设置静态初始化程序,并且不打算使用JUnit,请看一下TestNG。TestNG通过各种配置选项支持非静态的一次性初始化,所有配置选项均使用注释。
在TestNG中,这等效于:
@org.testng.annotations.BeforeClass
public void setUpOnce() {
// One time initialization.
}
拆解
@org.testng.annotations.AfterClass
public void tearDownOnce() {
// One time tear down.
}
对于等同于JUnit 4@Before
和的TestNG @After
,可以分别使用@BeforeMethod
和@AfterMethod
。
一个简单的if语句似乎也可以很好地工作:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class myTest {
public static boolean dbInit = false;
@Autowired
DbUtils dbUtils;
@Before
public void setUp(){
if(!dbInit){
dbUtils.dropTables();
dbUtils.createTables();
dbInit = true;
}
}
...
@AfterClass
在所有测试运行后都将消失的非静态等效项吗?
使用空构造函数是最简单的解决方案。您仍然可以在扩展类中重写构造函数。
但是对于所有继承来说,它并不是最佳的。这就是JUnit 4改用注释的原因。
另一种选择是在factory / util类中创建一个辅助方法,并让该方法完成工作。
如果您使用的是Spring,则应考虑使用@TestExecutionListeners
注释。像这样的测试:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({CustomTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class})
@ContextConfiguration("test-config.xml")
public class DemoTest {
AbstractTestExecutionListener
例如,Spring包含此空方法,您可以重写该方法:
public void beforeTestClass(TestContext testContext) throws Exception {
/* no-op */
}
注意:DependencyInjectionTestExecutionListener
添加custom时不要忽略/遗漏TestExecutionListeners
。如果这样做,所有的自动接线都将是null
。
beforeTestClass()
在上下文初始化之前或之后调用此方法?
轻松使用@BeforeAllMethods
/@AfterAllMethods
批注在实例上下文(非静态)中运行方法,在该方法中所有注入的值均可用。
为此有一个特殊的测试库:
https://mvnrepository.com/artifact/org.bitbucket.radistao.test/before-after-spring-test-runner/0.1.0
https://bitbucket.org/radistao/before-after-spring-test-runner/
唯一的限制:仅适用于Spring测试。
(我是该测试库的开发人员)
更新:请参阅Cherry的评论,以了解以下建议存在缺陷的原因。(将答案保留在此处而不是删除,因为注释可能会为其他人提供有用的信息,说明为什么此方法不起作用。)
如果使用依赖项注入(例如Spring),则值得考虑的另一种选择是@PostConstruct
。这将确保依赖项注入已完成,而在构造函数中则不会这样:
@PostConstruct
public void init() {
// One-time initialization...
}
@Before
和@After
方法将被调用6次!因此,在这种情况下,@PostConstruct
其行为类似于@Before
注释。您可以简单地对其进行测试:只需将2个测试方法放在测试类中,添加@PostConstruct public void init() {System.out.println("started");}
并在日志中查看打印了多少次。
只需使用@BeforeClass
:
@BeforeClass
public static void init() {
}
init
非静态是没有意义的,因为每个测试都在单独的实例中运行。该实例init
的运行将不匹配任何测试的实例。
您可能希望它为非静态的唯一原因是在子类中重写它,但是您也可以使用静态方法来做到这一点。只要使用相同的名称,就只会init
调用子类方法。