Java JUnit 4:在运行测试之前在测试套件中设置内容(如测试的 @BeforeClass 方法,仅用于测试套件)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/349842/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JUnit 4: Set up things in a test suite before tests are run (like a test's @BeforeClass method, just for a test suite)
提问by
I want to do some functional testing on a (restful) webservice. The testsuite contains a bunch of test cases, each of which performs a couple of HTTP requests on the webservice.
我想对(宁静的)网络服务进行一些功能测试。测试套件包含一堆测试用例,每个测试用例在 Web 服务上执行几个 HTTP 请求。
Naturally, the webservice has to run or the tests will fail. :-)
自然,网络服务必须运行,否则测试将失败。:-)
Starting the webservice takes a couple of minutes (it does some heavy data lifting), so I want to start it as infrequently as possible (at least all test cases that only GET resources from the service could share one).
启动 webservice 需要几分钟(它会执行一些繁重的数据提升),所以我想尽可能少地启动它(至少所有只从服务获取资源的测试用例都可以共享一个)。
So is there a way to do set up me the bomb in a test suite, before the tests are run like in a @BeforeClass method of a test case?
那么有没有办法在测试套件中设置炸弹,然后像测试用例的@BeforeClass 方法一样运行测试?
回答by sblundy
jUnit can't do that sort of thing -- though TestNG does have @BeforeSuite
and @AfterSuite
annotations. Normally, you get your build system to do it. In maven, there are the "pre-integration-test" and "post-integration-test" phases. In ANT, well you just add the steps to the task.
JUnit的不能做那种事情-虽然TestNG中确实有@BeforeSuite
和@AfterSuite
注释。通常,您可以让构建系统来执行此操作。在 maven 中,有“集成前测试”和“集成后测试”阶段。在 ANT 中,您只需将步骤添加到任务中即可。
Your question is pretty much a dup of Before and After Suite execution hook in jUnit 4.x, so I'd take a look at the suggestions over there.
您的问题几乎是 jUnit 4.x 中的Before and After Suite execution hook 的重复,所以我会看看那里的建议。
回答by Nick Holt
As an aside, it's a bad idea to have unit tests actually calling external resources like webservices, databases, etc.
顺便说一句,让单元测试实际调用外部资源(如 Web 服务、数据库等)是一个坏主意。
Unit tests should be super-quick to run and a delay of 'a couple of minutes' for each run of the suite will mean it won't be run as much as it should.
单元测试的运行速度应该非常快,并且套件的每次运行延迟“几分钟”将意味着它不会像应有的那样运行。
My advice:
我的建议:
Look at mocking external dependencies in unit tests with something like EasyMock (http://www.easymock.org/).
在单元测试中使用 EasyMock ( http://www.easymock.org/) 之类的东西来模拟外部依赖项。
Build a seperate suite of integration tests with something like Fitnesse (http://fitnesse.org/) or a homegrown solution that runs against a test environment and which is continually up.
使用 Fitnesse ( http://fitnesse.org/) 或针对测试环境运行且持续运行的本土解决方案构建单独的集成测试套件。
回答by Dan Vinton
One option is to use something like Apache Ant to launch your unit test suite. You can then put a target invocation before and after your junit target to start and stop your webservice:
一种选择是使用 Apache Ant 之类的东西来启动您的单元测试套件。然后,您可以在 junit 目标之前和之后放置一个目标调用来启动和停止您的网络服务:
<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"/>
You then run your suite using ant (or your integration tool of choice). Most IDEs have Ant support, and it makes it much easier to move your tests into a continous integration environment (many of which use Ant targets to define their own tests).
然后,您使用 ant(或您选择的集成工具)运行您的套件。大多数 IDE 都支持 Ant,并且可以更轻松地将测试移动到连续集成环境中(其中许多使用 Ant 目标来定义自己的测试)。
回答by Sled
The answer is now to create a @ClassRule
within your suite. The rule will be invoked before or after (depending on how you implement it) each test class is run. There are a few different base classes you can extend/implement. What is nice about class rules is that if you do not implement them as anonymous classes then you can reuse the code!
现在的答案是@ClassRule
在您的套件中创建一个。该规则将在每个测试类运行之前或之后(取决于您如何实现它)被调用。您可以扩展/实现几个不同的基类。类规则的好处在于,如果您不将它们实现为匿名类,那么您可以重用代码!
Here is an article about them: http://java.dzone.com/articles/junit-49-class-and-suite-level-rules
这是一篇关于它们的文章:http: //java.dzone.com/articles/junit-49-class-and-suite-level-rules
Here is some sample code to illustrate their use. Yes, it is trivial, but it should illustrate the life-cycle well enough for you to get started.
下面是一些示例代码来说明它们的用法。是的,这是微不足道的,但它应该足以很好地说明生命周期,以便您开始使用。
First the suite definition:
首先是套件定义:
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;
}
And now the test class definition:
现在测试类定义:
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 );
}
}