Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Junit-运行一次设置方法_Java_Junit - Fatal编程技术网

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
    }
}