Junit - 运行设置方法一次

时间:2012-08-23 08:46:38

标签: java junit

我设置了一个带有几个测试的类,而不是使用@Before我希望有一个在所有测试之前只执行一次的设置方法。 Junit 4.8有可能吗?

13 个答案:

答案 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