使用Junits测试线程

时间:2014-02-13 02:24:39

标签: java multithreading junit

我有调用另一个线程的代码,业务逻辑在run()方法中。 前代码:

public class Test {
    protected boolean stripObjects ;
    protected boolean catcharchiveObjects 
    public void runZipper(boolean strip,boolean createarchive) {        
        stripObjects = strip;
        catcharchiveObjects = createcatcharchive; 
        exThread czct = new exThread();        
        czct.start();        
    }

    private class exThread extends Thread() {
         public void run() {
         try {                                          
             if (strip)
                return;
              if(checkAction())
              {
                ....
              }
             //some business logic which generates a zipfile
            }
         catch (Exception e) {
          }
        }
    }
}

我为上面的代码编写了Junit,如下面。

public class JunitTest {
    public void testRunZipper() {
        Test testEx = new Test();
        testEx.runZipper(false,true);
        //assert statement to check whether zip file is created
    }
 }

当我运行Junit测试用例时,它失败并且没有生成zip。

然后我在调试模式下运行Junit,我看到调用czct.start()时它会运行run方法。但它立即返回调用函数,即runZipper()。

现在我修改了run()以将sysout添加为其中的第一个语句。现在,当我运行Junit时,它打印出sysout中的任何内容,然后控制返回到runZipper()。

任何人都可以帮助我解决这个问题,以便它执行run()中的所有语句。

提前致谢。

1 个答案:

答案 0 :(得分:1)

您需要在执行任何类型的多线程处理的类代码中添加“观察者”,同时仍需要进行单元测试。这个想法是:在每个逻辑步骤类之后向观察者发送信号。通常在prod环境中,没有人观察到这些信号,而在单元测试env或功能测试环境中,你会添加一个带有时间限制锁存器的观察者。

这是一个例子

public class MultithreadingInUnitTest {
    private Watcher watcher = new DefaultWatcher();

    public void runZipper() {
        exThread czct = new exThread();
        watcher.process(WatchedEvent.EVENT_1);
        czct.start();
    }

    private class exThread extends Thread {
        public void run() {
            try {
                //some business logic which generates a zipfile
            } catch (Exception e) {
            } finally {
                watcher.process(WatchedEvent.EVENT_2);
            }
        }
    }


    public void setWatcher(Watcher watcher) {
        this.watcher = watcher;
    }

    private class DefaultWatcher implements Watcher {
        @Override
        public void process(WatchedEvent event) {
            //Noop for production use
        }
    }
}

interface Watcher {
    public void process(WatchedEvent event);
}

enum WatchedEvent {
    EVENT_1, EVENT_2
}

这是你对它进行单元测试的方法。注意锁存器的时间限制

class JunitTest {
    public void testRunZipper() throws InterruptedException {
        final CountDownLatch latch = new CountDownLatch(1);
        Watcher watcher = new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                if (event == WatchedEvent.EVENT_2) { latch.countDown(); }
            }
        };
        MultithreadingInUnitTest testEx = new MultithreadingInUnitTest();
        testEx.setWatcher(watcher);

        testEx.runZipper();
        latch.await(10, TimeUnit.SECONDS);
        if (latch.getCount() != 0) { Assert.fail("Latch was never triggered"); }

        //assert statement to check whether zip file is created
    }

}