我设置了一个带有几个测试的类,而不是使用@Before
我希望有一个在所有测试之前只执行一次的设置方法。 Junit 4.8有可能吗?
答案 0 :(得分:185)
虽然我同意@assylias认为使用@BeforeClass
是一种经典的解决方案,但并不总是方便。使用@BeforeClass
注释的方法必须是静态的。对于需要测试用例的一些测试来说非常不方便。例如,基于Spring的测试使用@Autowired
来处理spring上下文中定义的服务。
在这种情况下,我个人使用带有setUp()
注释的常规@Before
方法并管理我的自定义static
(!)boolean
标记:
private static boolean setUpIsDone = false;
.....
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
答案 1 :(得分:82)
您可以使用the BeforeClass
annotation:
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
答案 2 :(得分:25)
JUnit 5现在有一个@BeforeAll注释:
表示应在所有@Test之前执行带注释的方法 当前类或类层次结构中的方法;类似于JUnit 4的@BeforeClass。这些方法必须是静态的。
JUnit 5的生命周期注释似乎终于搞定了!您可以猜测哪些注释无需查看(例如@BeforeEach @AfterAll)
答案 3 :(得分:8)
当setUp()
位于测试类的超类中时,可以按如下方式修改接受的答案:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
这应该适用于单个非静态setUp()
方法,但我无法在不偏离复杂反射的世界的情况下为tearDown()
生成等价物......赏金指向任何人谁可以!
答案 4 :(得分:2)
<强> 编辑: 强> 我刚刚调试时发现,在每次测试之前都会对类进行实例化。 我想@BeforeClass注释在这里是最好的。
您也可以在构造函数上进行设置,毕竟测试类 是一个类。 我不确定这是不是很糟糕,因为几乎所有其他方法都有注释,但它确实有效。你可以创建一个像这样的构造函数:
public UT () {
// initialize once here
}
@Test
// Some test here...
在测试之前会调用ctor,因为它们不是静态的。
答案 5 :(得分:2)
使用Spring的@PostConstruct方法来完成所有初始化工作,并且该方法会在执行任何@Test之前运行
答案 6 :(得分:0)
试试这个解决方案: https://stackoverflow.com/a/46274919/907576:
使用@BeforeAllMethods
/ @AfterAllMethods
注释,您可以在实例上下文中的Test类中执行任何方法,其中所有注入的值都可用。
答案 7 :(得分:0)
我的肮脏解决方案是:
foreach ($firstNames as $i => $firstName){
$description = new Description();
$description->setName($firstName, $lastNames[$i]);
$description->setDescription($descriptions[$i]);
echo $description->getDescription();
}
我将它用作所有testCases的基础。
答案 8 :(得分:0)
如果您不想强制声明在每个子测试中设置并检查的变量,则可以将其添加到SuperTest中:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
@Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
答案 9 :(得分:0)
我这样解决了这个问题:
将这部分代码添加到您的 Base 抽象类(我的意思是您在 setUpDriver()方法中初始化驱动程序的抽象类):
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
现在,如果您的测试类将从 Base 抽象类扩展-> setUpDriver()方法将首先执行@Test,然后才执行 ONE 每次运行时间很长。
答案 10 :(得分:0)
如果测试类的生命周期是每个类的,那么JUnit 5 @BeforeAll可以是非静态的,即用@TestInstance(Lifecycle.PER_CLASS)
注释测试类,您就可以了
答案 11 :(得分:0)
经过一段时间的试验,这是我的解决方案。我需要这个用于春季启动测试。我尝试使用@PostConstruct,不幸的是每次测试都会执行它。
public class TestClass {
private static TestClass testClass = null;
@Before
public void setUp() {
if (testClass == null) {
// set up once
testClass = this;
}
}
@AfterClass
public static void cleanUpAfterAll() {
testClass.cleanUpAfterAllTests();
}
private void cleanUpAfterAllTests() {
// final cleanup after all tests
}
@Test
public void test1() {
// test 1
}
@Test
public void test2() {
// test 2
}
}
答案 12 :(得分:0)
这是一个替代建议:
我要做的是让这个工作 创建一个名为 _warmup 或只是 _ 的方法 使用 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 注释测试类
仅当您运行类中的所有测试时才适用
它的缺点是包含额外的测试,它还会运行一个额外的@Before 和@After 通常建议您的测试方法与顺序无关,这违反了该规则,但是为什么有人希望在报告中随机排序测试我不知道所以 NAME_ASCENDING 是我一直使用的
但是这样做的好处是设置简单,代码最少,无需扩展类/运行程序等... 测试运行时间更准确,因为所有设置时间都报告在方法 _warmup