Java 使用JUnit在多线程环境中测试方法行为?
对于给定的方法,我想编写测试用例,以查看当多个线程同时运行时它的行为。可能听起来很愚蠢,但只是想知道是否有可能创建这样的场景?也可以将单元测试代码视为一个线程。当我尝试在多线程环境中测试某些东西时,通常我会执行以下操作: 我手动和手动启动了工作线程—包含测试方法的线程和单元测试线程中的其他线程 让单元测试线程在给定的时间内休眠,或者等待其他线程,然后我检查结果。Java 使用JUnit在多线程环境中测试方法行为?,java,unit-testing,tdd,junit4,Java,Unit Testing,Tdd,Junit4,对于给定的方法,我想编写测试用例,以查看当多个线程同时运行时它的行为。可能听起来很愚蠢,但只是想知道是否有可能创建这样的场景?也可以将单元测试代码视为一个线程。当我尝试在多线程环境中测试某些东西时,通常我会执行以下操作: 我手动和手动启动了工作线程—包含测试方法的线程和单元测试线程中的其他线程 让单元测试线程在给定的时间内休眠,或者等待其他线程,然后我检查结果。 问题是,单元测试线程可能不会向其他线程放弃执行,这就是为什么您必须以某种方式强制它。您无法直接控制如何将处理器时间分配给线程,因此必须
问题是,单元测试线程可能不会向其他线程放弃执行,这就是为什么您必须以某种方式强制它。您无法直接控制如何将处理器时间分配给线程,因此必须启动线程并让它们解决问题。将单元测试代码也视为一个线程。当我尝试在多线程环境中测试某些东西时,通常我会执行以下操作: 我手动和手动启动了工作线程—包含测试方法的线程和单元测试线程中的其他线程 让单元测试线程在给定的时间内休眠,或者等待其他线程,然后我检查结果。
问题是,单元测试线程可能不会向其他线程放弃执行,这就是为什么您必须以某种方式强制它。您无法直接控制如何将处理器时间分配给线程,因此您必须启动线程并让它们解决问题。您实际上可以在测试用例中启动线程,但我非常确定它不会执行您想要的操作。执行是不确定的 似乎有一些并发测试框架可能会有所帮助。他们使用特殊的技术来控制线程的行为,从而导致争用条件和其他不好的事情 我做了一个快速检查,发现
也许这让您走上了正确的轨道。您实际上可以在测试用例中启动线程,但我非常确定它不会做您想要的事情。执行是不确定的 似乎有一些并发测试框架可能会有所帮助。他们使用特殊的技术来控制线程的行为,从而导致争用条件和其他不好的事情 我做了一个快速检查,发现
也许这让您走上了正确的道路。这就是我最近在一些代码中实现这一点的方式:
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.Assert.*;
public class UtilTest
{
private final static int TEST_THREAD_COUNT = 10;
private volatile int threadsRun = 0;
private volatile List<String> nonUniqueIds = new ArrayList<>();
@Test
public void testUniqueIdGeneration()
{
final ExecutorService pool = Executors.newFixedThreadPool(TEST_THREAD_COUNT);
Runnable r = new Runnable()
{
@Override
public void run()
{
List<String> doneIds = new ArrayList<>();
for (int i = 1; i <= 100; i++)
{
String id = Util.generateId();
if (doneIds.contains(id))
{
nonUniqueIds.add(id);
break;
}
doneIds.add(id);
}
threadsRun++;
if (threadsRun >= TEST_THREAD_COUNT)
pool.shutdown();
}
};
for (int i = 0; i < TEST_THREAD_COUNT; i++)
{
pool.submit(r);
}
while (! pool.isShutdown())
{
//stay alive
}
if (nonUniqueIds.isEmpty() )
return;
for (String id: nonUniqueIds)
{
System.out.println("Non unique id: " + id);
}
assertTrue("Non unique ids found", false);
}
}
我最近在一些代码中就是这样实现的:
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.Assert.*;
public class UtilTest
{
private final static int TEST_THREAD_COUNT = 10;
private volatile int threadsRun = 0;
private volatile List<String> nonUniqueIds = new ArrayList<>();
@Test
public void testUniqueIdGeneration()
{
final ExecutorService pool = Executors.newFixedThreadPool(TEST_THREAD_COUNT);
Runnable r = new Runnable()
{
@Override
public void run()
{
List<String> doneIds = new ArrayList<>();
for (int i = 1; i <= 100; i++)
{
String id = Util.generateId();
if (doneIds.contains(id))
{
nonUniqueIds.add(id);
break;
}
doneIds.add(id);
}
threadsRun++;
if (threadsRun >= TEST_THREAD_COUNT)
pool.shutdown();
}
};
for (int i = 0; i < TEST_THREAD_COUNT; i++)
{
pool.submit(r);
}
while (! pool.isShutdown())
{
//stay alive
}
if (nonUniqueIds.isEmpty() )
return;
for (String id: nonUniqueIds)
{
System.out.println("Non unique id: " + id);
}
assertTrue("Non unique ids found", false);
}
}
这看起来非常相关,一定要尝试一下,让你知道这看起来非常相关,一定要尝试一下,让你知道也许不是你问题的真正答案,但要注意:当使用多线程时,你的代码将不是确定性的。您的测试可能会正常运行1000次,但在第1001次执行期间失败,没有任何代码更改。同意,这是一个重要因素,但如果我编写的所有测试都应该在多线程环境中运行,如何检查线程安全性?这对Memy来说非常关键,它可能不是对您的问题的真正答案,而是一个一般性的提示:当使用多线程时,您的代码将不是确定性的。您的测试可能会正常运行1000次,但在第1001次执行期间失败,没有任何代码更改。同意,这是一个重要因素,但如果我编写的所有测试都应该在多线程环境中运行,如何检查线程安全性?这对于meAren来说非常关键,难道没有第三方库可以抽象并发执行吗?我遇到过contiPerf,但它现在不活跃。如果您知道任何其他库可以从多个线程调用测试用例,并像contiPerf那样通过注释将其抽象出来,请告诉我。谢谢难道没有第三方库可以抽象并发执行吗?我遇到过contiPerf,但它现在不活跃。如果您知道任何其他库可以从多个线程调用测试用例,并像contiPerf那样通过注释将其抽象出来,请告诉我。谢谢