【问题标题】:Junit multiple threadsJunit 多个线程
【发布时间】:2011-10-18 14:52:07
【问题描述】:

我有一个提供参数并执行类的主要方法的测试用例。使用 Junit 让多个线程同时执行类的 main 方法的最佳方法是什么。

【问题讨论】:

    标签: java unit-testing testing junit


    【解决方案1】:

    不确定TestNG 是否适合您,但使用起来非常简单:

    @Test(invocationCount = 100, threadPoolSize = 10)
    public void myTest() { ... }
    

    这将导致从 10 个不同的线程调用测试方法 100 次。如果此测试通过并且您经常运行它,那么您可以相当确信被测代码是多线程安全的。

    【讨论】:

      【解决方案2】:

      你为什么要这样做?你的public static void main(String [])真的是由多个线程运行的吗?看起来很奇怪的设计,这就是我确定的原因。

      另一方面,如果您想测试程序的并行执行(因此每个都在单独的 JVM 中),它与多线程不同,JUnit 不会这样做,因为它在同一个 JVM 中执行.您仍然可以这样做,没问题,但请确保您知道其中的区别。

      关于 SO 的一些示例:

      【讨论】:

        【解决方案3】:

        这是一个轻量级的解决方案:

        这是您要测试的类:

        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 框架调用。重写 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;
                    }
                }
            }
        
        
        }
        

        这里是线程,可以多次调用。覆盖 test() 方法。

        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());
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-01-21
          • 1970-01-01
          • 2018-02-09
          • 2011-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-29
          • 1970-01-01
          相关资源
          最近更新 更多