java - 如何使用线程执行单元测试?

标签 java multithreading unit-testing junit

<分区>

执行摘要:当线程中出现断言错误时,单元测试不会终止。这是有道理的,因为不应允许一个线程使另一个线程崩溃。问题是我如何 1) 当第一个辅助线程崩溃时使整个测试失败或 2) 循环并确定每个线程全部完成后的状态(请参见下面的代码)。执行后者的一种方法是让每个线程都有一个状态变量,例如“boolean[] statuses”,并且“statuses[i] == false”意味着线程失败(这可以扩展以捕获更多信息)。然而,这不是我想要的:我希望它在抛出断言错误时像任何其他单元测试一样失败。这可能吗?是否可取?

我觉得很无聊,所以我决定在我的单元测试中生成一堆线程,然后让它们调用一个服务方法,只是为了解决这个问题。代码大致如下:

Thread[] threads = new Thread[MAX_THREADS];
for( int i = 0; i < threads.length; i++ ) {
    threads[i] = new Thread( new Runnable() {
        private final int ID = threadIdSequenceNumber++;
        public void run() {
            try {
                resultRefs[ID] = runTest( Integer.toString( ID ) ); // returns an object
            }
            catch( Throwable t ) { 
                // this code is EVIL - it catches even
                // Errors - don't copy it - more on this below
                final String message = "error testing thread with id => "
                            + ID;
                logger.debug( message, t );
                throw new IllegalStateException( message, t ); 
                // need to wrap throwable in a 
                // run time exception so it will compile
            }
        }
    } );
}

在此之后,我们将遍历线程数组并启动每个线程。之后,我们将等待他们全部完成。最后,我们将对结果引用执行一些检查。

for( Thread thread : threads )
    thread.start();

logger.debug( "waiting for threads to finish ..." );
boolean done = false;
while( !done ) {
    done = true;
    for( Thread thread : threads )
        if( thread.isAlive() )
            done = false;
}

for( int i = 0; i < resultRefs.length; i++ ) {
    assertTrue( "you've got the world messed, dawg!",
            myCondition(resultRefs[i]) );

问题来了。你有没有注意到那个讨厌的 try-catch-throwable block ?我只是将其添加为临时黑客,以便我可以看到发生了什么。在 runTest( String ) 中进行了一些断言,例如 assertNotNull( null ),但由于它在不同的线程中,因此不会导致单元测试失败!!!!

我的猜测是,我们需要以某种方式遍历线程数组,检查每个线程的状态,并在线程以令人讨厌的方式终止时手动引发断言错误。提供此信息的方法的名称是什么(死线程的堆栈跟踪)。

最佳答案

并发性是很难进行单元测试的事物之一。如果您只是想测试每个线程内的代码是否正在执行它应该测试的内容,那么您可能应该只测试与上下文隔离的代码。 如果在此示例中线程协作以达到结果,则您可以在不使用线程的情况下测试该协作。这将通过按顺序执行所有协作部分来完成。 如果你想测试竞争条件和这类事情,单元测试不是最好的方法。你会得到有时会失败有时不会失败的测试。 总而言之,我认为您的问题可能是您的单元测试级别太高。 希望这有帮助

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

相关文章:

java - Guava Sets.intersection 性能不佳

java - 这个数据库更新命令的计算是否正确?

javascript - AngularJS 单元测试,为什么有用?

c++ - 使用 C++ 在多线程应用程序中测量全局时间(挂钟)的最快方法

javascript - 引用错误 : notOk is not defined

c++ - 枚举类的 GoogleTest 测试错误打印

java - 如何在 Retrofit 调用中保存变量的值?

Java从某个索引迭代 map

android - 从不同的线程修改 View

java - Android,将数据推送到一组订阅线程的最佳方式?