当我运行以下代码时,两个测试用例都成为现实:
import static junit.framework.Assert.assertEquals;
import org.junit.Test;
public class MyTest{
private int count;
@Before
public void before(){
count=1;
}
@Test
public void test1(){
count++;
assertEquals(2, count);
}
@Test
public void test2(){
count++;
assertEquals(2, count);
}
}
预期行为
实际行为
为什么junit对于每个测试方法调用都是reinitializing class/variable
。
这是junit中的错误或故意提供。
答案 0 :(得分:20)
这是因为测试隔离。
不应该依赖另一个测试。
答案 1 :(得分:13)
MyTest
新实例对于每个测试方法,将创建{em} MyTest
的新实例,这是Junit的行为。
因此,在两种方法的情况下,变量count
将具有值1
,因此对于两种测试方法,count++
的值将为2
,因此测试用例通过。
public class MyTest{
public MyTest(){
// called n times
System.out.println("Constructor called for MyTest");
}
@Before //called n times
public void setUp(){
System.out.println("Before called for MyTest");
}
//n test methods
}
如果使用2种测试方法执行上述代码:
输出将是:
Constructor called for MyTest
Before called for MyTest
//test execution
Constructor called for MyTest
Before called for MyTest
答案 2 :(得分:6)
查看org.junit.runner.Runner
的文档:
默认的转轮实现保证了实例 测试用例类将在运行之前立即构建 测试并且跑步者将不保留对测试用例的引用 实例,通常使它们可用于垃圾收集。
单元测试应该是独立的,否则它将变得不可用。请注意,不保证执行方法的顺序(除非您使用注释@FixMethodOrder
)。
答案 3 :(得分:3)
不要在构造函数中初始化测试类状态,除非它是不可变的。
JUnit不会为每个@Test
实例化您的测试类。实际上它只会在每个方法之前运行标记为@Before
的方法,并且会在类中的所有测试之前运行@BeforeClass
个方法。
但是,您无法保证测试运行器实际上只使用测试类的一个实例来运行测试。它可以免费使用 - 考虑并行运行一系列测试,即使在不同的机器上也是如此。
虽然有一般的JUnit运行器设置可以控制它,但只需遵循JUnit设计并在仅标记为@Before
的方法中初始化测试状态就好了。
答案 4 :(得分:2)
如果要对所有测试使用测试类的成员变量,而不将其重新初始化为null,则将其设为 static 。
答案 5 :(得分:1)
在 JUnit5 中,此行为是使用 @TestInstance
注释控制的。注释可以将两个生命周期限定符之一作为值:
@TestInstance(Lifecycle.PER_CLASS)
:测试类将为类中的所有方法初始化一次。@TestInstance(Lifecycle.PER_METHOD)
:测试类将在每个测试方法之前重新初始化(其他答案中描述的行为)。如果测试类没有用 @TestInstance
注释,则默认行为是 PER_METHOD
。
有关详细信息,请参阅 JUnit5 用户指南中的 Test Instance Lifecycle。