现在把上面例子中的内隐类扩展自net.sourceforge.groboutils.junit.vl.TestRunnable包,我们必须像下面这样来重写runTest()方法。
private class DelayedHello
extends TestRunnable {
private String name;
private DelayedHello(
String name) {
this.name = name;
}
public void runTest() throws Throwable {
long l;
l = Math.round(2 + Math.random() * 3);
// Sleep between 2-5 seconds
Thread.sleep(l * 1000);
System.out.println(
"Delayed Hello World " + name);
}
}
这时,我们全然不用创建工作线程。MultiThreadedTestRunner将在底层做这件事情,你重写runTest()方法来替实现run()方法,runTest()方法被后面的MultiThreadedTestRunner类调用———我们自己不会调用它。
一旦TestRunnable被定义,我们必须定义新的测试用例。在我们的testExampleThread()方法中,我们实例化了几个TestRunnable对象,并且把它们添加到一个数组中。然后,示例化MultiThreadedTestRunner类,把TestRunnable对象数组做为参数传递给这人类的构造子函数。现在,我们有了一个MultiThreadedTestRunner类的实例,我们就可以调用它的runTestRunnables()方法来执行测试。
MultiThreadedTestRunner(和Junit中的TestRunner不一样)在继续执行之前,将等待每一个线程运行终止。它也为通过构造器传递给它的每个TestRunnalbe对象创建工作线程并且调用异步的start()方法。这就意味着你没有必要通过创建你自己的线程来跳过这个障碍———MultiThreadedTestRunner会为你做这件事。下面是ExampleTest的最终版:
import junit.framework.*;
import net.sourceforge.groboutils.junit.v1.*;
public class ExampleTest extends TestCase {
private TestRunnable testRunnable;
private class DelayedHello
extends TestRunnable {
private String name;
private DelayedHello(
String name) {
this.name = name;
}
public void runTest() throws Throwable {
long l;
l = Math.round(2 + Math.random() * 3);
// Sleep between 2-5 seconds
Thread.sleep(l * 1000);
System.out.println(
"Delayed Hello World " + name);
}
}
/**在你的测试用例中使用MultiThreadedTestRunner,
* MTTR需要一个TestRunnable对象做为它的构造器的参数
* MTTR创建以后,调用runTestRunnables()方法来运行它
*/
public void testExampleThread()
throws Throwable {
//实例化 TestRunnable 类
TestRunnable tr1, tr2, tr3;
tr1 = new DelayedHello("1");
tr2 = new DelayedHello("2");
tr3 = new DelayedHello("3");
//把实例传递给 MTTR
TestRunnable[] trs = {tr1, tr2, tr3};
MultiThreadedTestRunner mttr =
new MultiThreadedTestRunner(trs);
//执行MTTR和线程
mttr.runTestRunnables();
}
/**
* 标准的 main() 和 suite() 方法
*/
public static void main (String[] args) {
String[] name =
{ ExampleTest.class.getName() };
junit.textui.TestRunner.main(name);
}
public static Test suite() {
return new TestSuite(ExampleTest.class);
}
}
上面的例子中,每个线程将会在你发出测试指令后,在2到5秒之间向你返回它们的输出,它们不仅按时间显示,而且是以一个随机的顺序来显示。这个单元测试只有所有的线程都执行完成后才会结束。由于外加了MultiThreadedTestRunner,所以Junit继续执行测试用例之前,必须耐心的等待TestRunnables执行完成它们的工作,做为可选项,你可以为MultiThreadedTestRunner的执行分配最大的执行时间(这样以便你脱离线程,而不挂起测试)。
要编译运行ExampleTest,你必须在你的CLASSPATH环境变量中指定junit.jar和GroboUtils-2-core.jar两个类库的位置。这样你就会看到每人线程以随机的顺序来输出 “Delayed Hedllo World”
结束语
写一个多线程的单元测试不用感到苦脑,GroboUtils类库为编写多线程的单元测试提供了一个清晰简单的API接口,通过把这个类库添加到你的工具包中,你就可以把单元测试扩展到模拟繁重的WEB网络通讯和并发的数据库处理,以及对你的同步方法进行压力测试。
文章来源于领测软件测试网 https://www.ltesting.net/