Java Junit-运行一次设置方法
我用几个测试设置了一个类,而不是在所有测试之前使用Java Junit-运行一次设置方法,java,junit,Java,Junit,我用几个测试设置了一个类,而不是在所有测试之前使用@Before,我希望有一个setup方法,在所有测试之前只执行一次。Junit 4.8是否可能实现这一点?您可以使用: 虽然我同意@assylias的观点,使用@BeforeClass是一个经典的解决方案,但并不总是很方便。用@BeforeClass注释的方法必须是静态的。对于一些需要测试用例实例的测试来说是非常不方便的。例如,基于Spring的测试使用@Autowired处理Spring上下文中定义的服务 在这种情况下,我个人使用常规的set
@Before
,我希望有一个setup方法,在所有测试之前只执行一次。Junit 4.8是否可能实现这一点?您可以使用:
虽然我同意@assylias的观点,使用
@BeforeClass
是一个经典的解决方案,但并不总是很方便。用@BeforeClass
注释的方法必须是静态的。对于一些需要测试用例实例的测试来说是非常不方便的。例如,基于Spring的测试使用@Autowired
处理Spring上下文中定义的服务
在这种情况下,我个人使用常规的setUp()
方法,在注释之前使用@进行注释,并管理我的自定义静态
(!)布尔标记:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
当setUp()
在测试类的超类中时(例如下面的AbstractTestBase
),可按如下方式修改接受的答案:
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();
}
}
公共抽象类AbstractTestBase{
私有静态类编辑:
我刚刚在调试时发现,在每次测试之前也会实例化该类。
我想@BeforeClass注释在这里是最好的
您也可以在构造函数上设置,测试类毕竟是一个类。
我不确定这是否是一种不好的做法,因为几乎所有其他方法都有注释,但它是有效的。您可以创建这样的构造函数:
public UT () {
// initialize once here
}
@Test
// Some test here...
测试之前将调用ctor,因为它们不是静态的。JUnit 5现在有一个@BeforeAll注释:
表示带注释的方法应在所有@Test之前执行
当前类或类层次结构中的方法;类似于JUnit
4的@BeforeClass。此类方法必须是静态的
JUnit 5的生命周期注释似乎终于正确了!您甚至不需要查看即可猜出可用的注释(例如@beforeach@AfterAll)尝试以下解决方案:
:
使用@BeforeAllMethods
/@AfterAllMethods
注释,您可以在实例上下文中执行测试类中的任何方法,其中所有注入值都可用。我的脏解决方案是:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
@Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
我使用它作为所有测试用例的基础。如果您不想强制声明在每个子测试上设置和检查的变量,那么将其添加到超级测试可以:
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 ...
}
}
公共抽象类超级测试{
私有静态最终ConcurrentHashMap INITIALIZED=新ConcurrentHashMap();
受保护的最终布尔值已初始化(){
最终布尔值[]缺失={false};
INITIALIZED.computeIfAbsent(this.getClass(),(klass)->{
返回缺席[0]=true;
});
返回!缺席[0];
}
}
公共类子测试扩展了SuperTest{
@以前
在()之前公开无效{
if(super.initialized())返回;
魔术
}
}
我这样解决了这个问题:
将这部分代码添加到基础抽象类(我是指在setUpDriver()方法中初始化驱动程序的抽象类):
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
现在,如果您的测试类将从Base扩展到abstract class->setUpDriver()方法将在第一次@Test之前执行,每次运行一次。使用Spring的@PostConstruct方法来完成所有初始化工作,并且此方法在执行任何@Test之前运行,前提是测试类的生命周期是每个类,即用注释测试类code>@TestInstance(Lifecycle.PER_CLASS)
经过一段时间的实验后,您可以开始了这是我的解决方案。我在spring boot测试中需要它。我尝试使用@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
}
}
我不能使用这个,我有一些基于非静态组件的安装方法,比如getClass()@Bober02 BeforeClass确实需要是静态的。如果你不能使用它,另一个答案提供了一个解决方法。确定你不能使用你想要的ClassYouWant.class
来代替你的getClass()调用吗?这是实际的Java:String.class.getName()
@MikCorvent我理解这个问题是“类中的所有测试”-但你是对的,这可能不是OP想要的。在Kenny Cason的评论中添加了为什么它必须是静态的。它必须是静态的,因为JUnit为每个@test方法实例化了测试类的新实例。实例变量将重置为它的默认值(false)如果不是静态的,则适用于每个实例。有关更多信息,请参阅:除了setUp()之外
方法在超类中-我在下面发布了一个试图解决这个问题的帖子。我不太愿意对一个拥有84k代表的人说这句话,但BeforeClass实际上并没有回答这个问题:BeforeClass在每个测试类的开头都运行。但是OP要求的是一个“在所有测试之前只运行一次”的类。你提出的解决方案可以做到这一点,但你必须让你所有的测试类扩展一个“CommonTest”类…@MikCorvent,IMHO OP询问了他的测试用例中的所有测试,而不是所有的测试。因此,你的评论没有那么重要。顺便说一句,即使他的声誉很高,也不要担心对任何人说什么。至少我是这么做的:)2012年8月,当我回答这个问题时,我的声誉明显下降。在我的情况下,设置中初始化的变量在每次测试后都会重置,因此只初始化一次是毫无意义的。看看RunListener:它有相同的问题是@BeforeClass
,它需要是静态的。IMO@AlexR的解决方案on更好。@zengr倾向于同意你的观点:正如我对AlexR所说的,他的解决方案要求所有测试类都从CommonTest类中派生,如果它只运行一次。但它尽可能简单,而且你可能不应该使用“幻想”当语言中有一个简单的机制可用时,框架提供的解决方案
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
}
}