JUnit 4:在测试运行之前在测试套件中设置东西(比如测试的@BeforeClass方法,仅​​用于测试套件)

时间:2008-12-08 15:23:01

标签: java unit-testing junit functional-programming

我想在(restful)webservice上做一些功能测试。 testsuite包含一堆测试用例,每个测试用例在Web服务上执行几个HTTP请求。

当然,Web服务必须运行或测试失败。 : - )

启动webservice需要几分钟(它会提升一些重量级数据),所以我想尽可能少地启动它(至少所有只有来自服务的GET资源可以共享一个的测试用例)。

在测试运行之前,有没有办法在测试套件中设置炸弹,就像测试用例的@BeforeClass方法一样?

4 个答案:

答案 0 :(得分:22)

现在的答案是在您的套件中创建@ClassRule。将在运行每个测试类之前或之后(取决于您如何实现它)调用该规则。您可以扩展/实现几个不同的基类。类规则的好处是,如果你不将它们实现为匿名类,那么你可以重用代码!

以下是关于它们的文章:http://java.dzone.com/articles/junit-49-class-and-suite-level-rules

以下是一些示例代码来说明它们的用法。是的,这是微不足道的,但它应该足以说明你的生命周期,以便你开始。

首先是套件定义:

import org.junit.*;
import org.junit.rules.ExternalResource;
import org.junit.runners.Suite;
import org.junit.runner.RunWith;


@RunWith( Suite.class )
@Suite.SuiteClasses( { 
    RuleTest.class,
} )
public class RuleSuite{

    private static int bCount = 0;
    private static int aCount = 0;

    @ClassRule
    public static ExternalResource testRule = new ExternalResource(){
            @Override
            protected void before() throws Throwable{
                System.err.println( "before test class: " + ++bCount );
                sss = "asdf";
            };

            @Override
            protected void after(){
                System.err.println( "after test class: " + ++aCount );
            };
        };


    public static String sss;
}

现在测试类定义:

import static org.junit.Assert.*;

import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;

public class RuleTest {

    @Test
    public void asdf1(){
        assertNotNull( "A value should've been set by a rule.", RuleSuite.sss );
    }

    @Test
    public void asdf2(){
        assertEquals( "This value should be set by the rule.", "asdf", RuleSuite.sss );
    }
}

答案 1 :(得分:1)

jUnit无法做到这一点 - 尽管TestNG确实有@BeforeSuite@AfterSuite注释。通常,您可以使用构建系统来执行此操作。在maven中,有“预集成测试”和“集成后测试”阶段。在ANT中,您只需添加步骤即可完成任务。

你的问题几乎是Before and After Suite execution hook in jUnit 4.x的问题,所以我会看看那边的建议。

答案 2 :(得分:0)

一种选择是使用像Apache Ant这样的东西来启动你的单元测试套件。 然后,您可以在junit目标之前和之后放置目标调用,以启动和停止Web服务:

<target name="start.webservice"><!-- starts the webservice... --></target>
<target name="stop.webservice"><!-- stops the webservice... --></target>
<target name="unit.test"><!-- just runs the tests... --></target>

<target name="run.test.suite" 
        depends="start.webservice, unit.test, stop.webservice"/>

然后使用ant(或您选择的集成工具)运行您的套件。大多数IDE都具有Ant支持,它使得将测试移动到连续集成环境(其中许多使用Ant目标来定义自己的测试)变得更加容易。

答案 3 :(得分:-2)

顺便说一句,让单元测试实际调用Web服务,数据库等外部资源是个坏主意。

单元测试应该超级快速运行,并且每次运行套件的“几分钟”延迟意味着它不会运行得那么多。

我的建议:

使用EasyMock(http://www.easymock.org/)等单元测试来模拟外部依赖项。

使用Fitnesse(http://fitnesse.org/)或本地解决方案构建一个独立的集成测试套件,该解决方案针对测试环境运行并持续运行。