Awaitility是对并发生产代码进行单元测试的绝佳工具。
问题:是否有一种工具可以轻松编写并发测试代码?
假设我想测试java.util.concurrent.LinkedBlockingQueue
。
public class BlockingQueueTest {
private LinkedBlockingQueue<String> out;
@Before
public void setUp() {
out = new LinkedBlockingQueue<>();
}
@Test
public void putThenGet() throws InterruptedException {
// that's easy because it can be done in one thread
out.put("Hello");
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
@Test
public void getBeforePut() throws InterruptedException {
// that's more tricky because it can't be done with one thread
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> {
Thread.sleep(100);
out.put("Hello");
return null;
});
executorService.shutdown();
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
getBeforePut()
代码并不好玩。有没有办法让它变得不那么难,更具可读性呢?
@Test
public void getBeforePut2() throws InterruptedException {
// Wanted: DSL for concurrent test-code
Concurrently.sleep(100, TimeUnit.MILLISECONDS).andThen(() -> out.put("Hello"));
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
答案 0 :(得分:2)
对我来说,使用TestNG是最简单的方式:
@Test(threadPoolSize = 10, invocationCount = 15, timeOut = 1000)
public void testPut(){
out.put("Hello");
}
此测试将在10个线程中运行15次,并且不应超过1000毫秒。
您还可以创建依赖于其他测试的测试
@Test(dependsOnMethods = "testPut")
public void testGetAfterPut{
String taken = out.take();
assertThat(taken).isEqualTo("Hello");
}
答案 1 :(得分:0)
现在,我正在用Kotlin编写所有测试。通过Kotlin测试,这既轻松又有趣!
使用线程进行测试时值得一提的是JUnit's @Timeout Annotation,这可以防止错误的测试无限运行。
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Timeout
import java.util.concurrent.LinkedBlockingQueue
import kotlin.concurrent.thread
class BlockingQueueKotlinTests {
// objectUnderTest
private val out = LinkedBlockingQueue<String>()
@Test
fun `put then get`() {
// that's easy because it can be done in one thread
out.put("Hello")
val taken = out.take()
assertThat(taken).isEqualTo("Hello")
}
@Test
@Timeout(1)
fun `get before put`() {
// thanks to kotlin it's really easy to do that in another thread
thread {
Thread.sleep(100)
out.put("kotlin is great!")
}
val taken = out.take()
assertThat(taken).isEqualTo("kotlin is great!")
}
}