Java Junit多线程
我有一个提供参数并执行类的主方法的测试用例。使用Junit让多个线程同时执行类的主方法的最佳方法是什么?您的Java Junit多线程,java,unit-testing,testing,junit,Java,Unit Testing,Testing,Junit,我有一个提供参数并执行类的主方法的测试用例。使用Junit让多个线程同时执行类的主方法的最佳方法是什么?您的公共静态void main(String[])是否真的由多个线程运行?看起来是个奇怪的设计,这就是为什么我要确定 另一方面,如果您想测试程序的并行执行(因此每个程序都在一个单独的JVM中),那么它与多线程不同,JUnit不会这样做,因为它在同一个JVM中执行。你仍然可以这样做,没问题,但要确保你知道其中的区别 例如: (用于在单独JVM中执行并行测试的一些其他工具) 不确定是否是您的选
公共静态void main(String[])
是否真的由多个线程运行?看起来是个奇怪的设计,这就是为什么我要确定
另一方面,如果您想测试程序的并行执行(因此每个程序都在一个单独的JVM中),那么它与多线程不同,JUnit不会这样做,因为它在同一个JVM中执行。你仍然可以这样做,没问题,但要确保你知道其中的区别
例如:
- (用于在单独JVM中执行并行测试的一些其他工具)
@Test(invocationCount = 100, threadPoolSize = 10)
public void myTest() { ... }
这将导致测试方法从10个不同的线程调用100次。如果此测试通过,并且您经常运行它,那么您可以非常确信测试中的代码是多线程安全的。这里有一个轻量级解决方案: 以下是您要测试的类:
package mTTest;
/**
* UUT class is the Unit Under Test. This will be tested.
* It has two simple method:
* push(): sets the message string if it's null, and waits otherwise.
* pop(): if there is any message sets it null and returns it.
*
*/
public class UUT {
String message = null;
synchronized void push(String msg){
while (null != message) {
try {
wait();
} catch (InterruptedException e) {
}
}
message = msg;
notifyAll();
}
synchronized String pop(){
while (null == message) {
try {
wait();
} catch (InterruptedException e) {
}
}
String ret = message;
message = null;
notifyAll();
return ret;
}
}
这是测试课。这将在JUnit框架的bz中调用。重写multiTest()方法。
包装mTTest
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import org.junit.Test;
/**
* This is the JUnit test class. Method in this class will invoked by the JUnit
* framework.
*/
public class DUTTest {
/**
* Stores sub test threads errors.
*/
private static List<AssertionError> errors;
/**
* sub test threads call this function with they errors.
* @param err
*/
static void handle(AssertionError err){
errors.add(err);
}
/**
* Simpler single thread test
* @throws InterruptedException
*/
@Test
public void testSingle() {
UUT dut = new UUT();
dut.push("hello");
assertEquals("set-get", "hello", dut.message);
}
/**
* Complex multi-thread test
* @throws InterruptedException
*/
@Test
public void testMulti() throws Exception {
/*
* Initialization
*/
errors = Collections.synchronizedList(new ArrayList<AssertionError>());
UUT dut = new UUT();
MyTestThread th = new MyTestThread(dut);
/*
* Tests
*/
dut.push("hello");
assertEquals("set-get", "hello", dut.message);
th.start();
dut.push("hello");
th.join();
/*
* Error handling
*/
ListIterator<AssertionError> iter = errors.listIterator(errors.size());
while (iter.hasPrevious()) {
AssertionError err = iter.previous();
err.printStackTrace();
if(iter.previousIndex() == -1){
throw err;
}
}
}
}
package mTTest;
import static org.junit.Assert.assertEquals;
/**
* This is the custom test thread class. The main test thread (which is started
* by JUnit) starts this thread.
*
*/
public class MyTestThread extends Thread {
UUT dut;
/**
* Constructor
* @param dut : should be overwritten to your custom DUT-class
*/
public MyTestThread(UUT dut) {
this.dut =dut;
}
/**
* run() method is final to prevent overriding. Override test instead.
* It just calls the test method and handle the assertion errors.
*/
@Override
public final void run() {
try{
test();
} catch (AssertionError ex){
DUTTest.handle(ex);
}
}
/**
* Write your tests here. run calls this function.
*/
void test(){
assertEquals("set-get", "This will cause an ERROR", dut.pop());
assertEquals("set-get", "hello", dut.pop());
}
}