java - 如何对java多线程进行单元测试

标签 java multithreading unit-testing callback

问题是我有一个方法来启动一个新线程来完成一项耗时的工作。我想测试回调结果,但子线程可能仍在运行,因此,我得到的不是正确的 stub 。

我认为代码可以解释自己:

public class JustAClass {
    //it is a callback for async   
    public interface JustACallBack {
        void callFunc(JustAResult result);
    }

    //this is the result interface
    public interface JustAResult {
    }

    //this is a real class for the interface
    public class JustAResultReal implements JustAResult{
        public JustAResultReal(String content) {this.content = content;}
        public String content;
    }

    //here is the key function
    public void threadFunc(final JustACallBack callBack) {
        BCCache.executorService.execute(new Runnable() {
            @Override
            public void run() {
                //just to simulate a time-consuming task
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //now we callback
                callBack.callFunc(new JustAResultReal("can you reach me"));
            }
        });
    }
}

测试函数可以是(我正在使用mockito):

@Test
public void testThreadFunc() throws Exception {

    JustAClass justAClass = new JustAClass();

    JustAClass.JustACallBack callBack = Mockito.mock(JustAClass.JustACallBack.class);

    justAClass.threadFunc(callBack);

    //add this line, we can get the expected result
    Thread.sleep(1200);

    Mockito.verify(callBack).callFunc(captor.capture());

    System.out.println(((JustAClass.JustAResultReal)captor.getValue()).content);
}

我知道我们可以添加一个sleep来等待并期望子线程在这段时间内退出,但是还有更好的方法吗?实际上我怎么知道子线程需要多长时间?设置很长的时间可能是一种方法,但似乎不太好。

最佳答案

@stalet 的答案中的一般方法很接近,但不太有效,因为主线程不会注意到来自单独线程的任何断言失败。因此,您的测试将始终通过,即使它不应该通过。相反,请尝试使用 ConcurrentUnit (我创作):

@Test
public void testInvoke() throws Throwable {
    Waiter waiter = new Waiter();
    JustAClass justAClass = new JustAClass();
    JustAClass.JustACallBack callBack = new JustAClass.JustACallBack() {
        @Override
        public void callFunc(final JustAClass.JustAResult result) {
            waiter.assertNotNull(result);
            waiter.assertTrue(result instanceof JustAClass.JustAResultReal);
            waiter.resume();
        }
    };

    justAClass.threadFunc(callBack);
    waiter.await(1200, TimeUnit.SECONDS);
}

这里的关键是 ConcurrentUnit 的 Waiter 将正确向主测试线程报告任何断言失败,并且测试将按其应有的方式通过或失败。

关于java - 如何对java多线程进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33688787/

相关文章:

scala - Akka Actor在单元测试期间出现异常后重启

java - 如何列出在特定类加载器中加载的所有类

java - java如何存储文字?

java - 暴力破解不起作用,我找不到 key

java - BasicDataSource close() 方法不关闭连接

java - 我的 getStatement 方法线程安全吗?

multithreading - 使用 MVar 在 Haskell 中创建线程安全队列(也许?)

PHPUnit Mock 似乎没有调用公共(public)函数

c++ - 在什么情况下,您在 C++ 中使用信号量而不是互斥量?

java - 使用groovy对java类进行单元测试