unit-testing - 如果在另一个线程中抛出异常,则单元测试失败

标签 unit-testing junit testng hamcrest assertj

目前,每当我需要使测试失败以响应另一个线程中抛出的异常时,我会编写如下内容:

package com.example;

import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;

import static java.util.Arrays.asList;
import static java.util.Collections.synchronizedList;
import static org.testng.Assert.fail;

public final class T {
  @Test
  public void testFailureFromLambda() throws Throwable {
    final List<Throwable> errors = synchronizedList(new ArrayList<>());

    asList("0", "1", "2").parallelStream().forEach(s -> {
      try {
        /*
         * The actual code under test here.
         */
        throw new Exception("Error " + s);
      } catch (final Throwable t) {
        errors.add(t);
      }
    });

    if (!errors.isEmpty()) {
      errors.forEach(Throwable::printStackTrace);

      final Throwable firstError = errors.iterator().next();
      fail(firstError.getMessage(), firstError);
    }
  }
}

同步列表可以替换为 AtomicReference<Throwable> ,但总的来说,代码几乎保持不变。

是否有使用 Java 中可用的任何测试框架( TestNGJUnitHamcrestAssertJ 等)来执行相同操作的标准(且不那么冗长)方法吗?

最佳答案

默认情况下,TestNG 会在抛出异常时使测试方法失败。我相信 JUnit 也会发生同样的事情,其中​​它将测试标记为 errored , 如果它抛出一个意外的异常。

如果您要处理 Streams ,那么您需要将其包裹在 RuntimeException 中变体,因此 Java 不会提示。 TestNG 会自动使测试失败。

这是一个示例:

@Test
public void testFailureFromLambdaRefactored() {
    asList("0", "1", "2").parallelStream().forEach(s -> {
        try {
        /*
        * The actual code under test here.
        */
            if (s.equals("2")) {
                throw new Exception("Error " + s);
            }
        } catch (final Throwable t) {
            throw new RuntimeException(t);
        }
    });
}

这适用于涉及 lambda 和流的场景。一般而言,如果您想了解从 @Test 分出的新线程中发生的异常。方法,那么你需要使用 ExecutorService .

这是一个示例:
@Test
public void testFailureInAnotherThread() throws InterruptedException, ExecutionException {
    List<String> list = asList("0", "1", "2");
    ExecutorService service = Executors.newFixedThreadPool(2);
    List<Future<Void>> futures = service.invokeAll(Arrays.asList(new Worker(list)));
    for (Future future : futures) {
        future.get();
    }

}

public static class Worker implements Callable<Void> {
    private List<String> list;

    public Worker(List<String> list) {
        this.list = list;
    }

    @Override
    public Void call() throws Exception {
        for (String s : list) {
            if (s.equals("2")) {
                throw new Exception("Error " + s);
            }
        }
        return null;
    }
}

关于unit-testing - 如果在另一个线程中抛出异常,则单元测试失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45759903/

相关文章:

unit-testing - 当类具有外部依赖项时如何编写有效的单元测试?

java - 如何手动生成JUnit测试报告

java - 测试 TestNG 中所有包中的所有 JUnit 文件

unit-testing - 测试后端 api 端点是否被视为单元测试?

c# 使用套接字进行单元测试

java - 如何使用 surefire 插件在自定义文件夹结构中运行测试

java - 尝试测试 SQLiteOpenHelper 但 getWritableDatabase() 抛出 Null

java - 当范围标记为 'test' 时导入 testng 类

java - 无法点击复选框

unit-testing - 如何在 Golang 中实现 stub ? stub 和模拟之间有什么区别?