59

我使用 Jfunc 构建了我现有的框架,它提供了一种工具,即使在测试用例中的一个断言失败时也可以继续执行。Jfunc 使用 junit 3.x 框架。但是现在我们正在迁移到 junit4,所以我不能再使用 Jfunc 并用 junit 4.10 jar 替换它。
现在的问题是,因为我们在框架中广泛使用了 jfunc,并且使用 junit 4,我们希望即使在测试用例中的一个断言失败时,我们的代码也能继续执行。
有没有人对此有任何建议/想法,我知道在junit中测试需要更加原子,即每个测试用例一个断言,但由于某种原因我们不能在我们的框架中这样做。

4

7 回答 7

75

您可以使用ErrorCollector规则执行此操作。

要使用它,首先将规则添加为测试类中的字段:

public class MyTest {
    @Rule
    public ErrorCollector collector = new ErrorCollector();

    //...tests...
}

然后将您的断言替换为对collector.checkThat(...).

例如

@Test
public void myTest() {
    collector.checkThat("a", equalTo("b"));
    collector.checkThat(1, equalTo(2));
}
于 2012-04-19T05:12:31.090 回答
22

我也使用 ErrorCollector 但也使用 assertThat 并将它们放在 try catch 块中。

import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;

@Rule
public ErrorCollector collector = new ErrorCollector();

@Test
public void calculatedValueShouldEqualExpected() {
    try {
        assertThat(calculatedValue(), is(expected));
    } catch (Throwable t) {
        collector.addError(t);
        // do something
    }
}
于 2012-07-12T03:35:02.140 回答
5

你也可以使用assertj - 软断言

@Test
public void testCollectErrors(){
   SoftAssertions softly = new SoftAssertions();
   softly.assertThat(true).isFalse();
   softly.assertThat(false).isTrue();
   // Don't forget to call SoftAssertions global verification !
   softly.assertAll();
}

还存在其他使用它的方式,无需手动调用 softly.assertAll();

  1. 有规则
  2. 可自动关闭
  3. 使用静态 assertSoftly 方法
于 2016-12-20T13:00:24.763 回答
3

使用 try/finally 块。这在我的情况下有效:

...
try {
    assert(...)
} finally {
    // code to be executed after assert
}
...
于 2015-08-29T18:37:36.573 回答
0

Try - catch,在“try”中使用断言,在“catch”中将可能的错误添加到集合中。然后在测试结束时在 tearDown() 中抛出异常。因此,如果断言中出现失败/错误,它将被捕获并继续测试。(示例中的集合是静态的,您也可以在 setUp() 中为每个 @Test 创建新实例)

    public static List<String> errors = new ArrayList<>();


    try {
        //some assert...
    }
    catch (AssertionError error) {
        errors.add(error.toString());
    }



    @After
    public void tearDown() {

        try {
            if (!errors.isEmpty()) {
                throw new AssertionError(errors);
            }
        }
        finally {
            //empty list because it's static, alternatively make instance for each test in setUp()
            errors.clear();
        }
    }
于 2018-11-20T08:46:19.080 回答
0

我创建了自己的简单断言类。易于使用您的用例进行扩展:

public class MyEquals {

public static void checkTestSummary(MyTestSummary myTestSummary) {
    final List<MyTestResult> conditions = myTestSummary.getTestResults();
    final int total = conditions.size();

    final boolean isSuccessful = myTestSummary.isSuccessful();
    if (isSuccessful) {
        System.out.println(format("All [%s] conditions are successful!", total));
    } else {
        final List<MyTestResult> failedConditions = conditions.stream().filter(MyTestResult::isTestResult).collect(Collectors.toList());
        System.out.println(format("\nNot yet.. [%s out of %s] conditions are failed", failedConditions.size(), total));
    }

    if (!isSuccessful) {
        for (int i = 0; i < total; i++) {
            final MyTestResult myTestResult = conditions.get(i);
            if (myTestResult.isTestResult()) {
                System.out.println(format("  Success [%s of %s] => Expected %s Actual %s Good!", i + 1, total, myTestResult.getExpected(), myTestResult.getActual()));
            } else {
                System.out.println(format("!! Failed [%s of %s] => Expected %s Actual %s", i + 1, total, myTestResult.getExpected(), myTestResult.getActual()));
            }
        }
    }

    assertTrue(isSuccessful);
}

public static void myAssertEquals(MyTestSummary myTestSummary, Object expected, Object actual) {
    if (checkEquals(expected, actual)) {
        assertEquals(expected, actual);
        myTestSummary.addSuccessfulResult(expected, actual);
    } else {
        myTestSummary.addFailedResult(expected, actual);
        myTestSummary.setSuccessful(false);
    }
}

public static boolean checkEquals(Object value1, Object value2) {
    if (value1 == null && value2 == null) {
        return true;
    } else if (value1 != null && value2 == null) {
        return false;
    } else if (value1 == null && value2 != null) {
        return false;
    } else if (value1 != null && value2 != null) {
        return value1.equals(value2);
    }
    return false;
}

}

@Builder
@Value
public class MyTestResult {

    String expected;

    String actual;

    boolean testResult;

 }



@Data
public class MyTestSummary {

private boolean successful = true;

private List<MyTestResult> testResults = new ArrayList<>();

public MyTestSummary() {
}

public void addSuccessfulResult(Object expected, Object actual) {
    getTestResults().add(MyTestResult.builder()
        .expected(String.valueOf(expected))
        .actual(String.valueOf(actual))
        .testResult(true)
        .build()
    );
}

public void addFailedResult(Object expected, Object actual) {
    getTestResults().add(MyTestResult.builder()
        .expected(String.valueOf(expected))
        .actual(String.valueOf(actual))
        .testResult(false)
        .build()
    );
}
}

在junit测试中的使用

@Test
public void testThat() {
    MyTestSummary myTestSummary = new MyTestSummary();
    myAssertEquals(myTestSummary, 10, 5 + 5);
    myAssertEquals(myTestSummary, "xxx", "x" + "x");
    checkTestSummary(myTestSummary);
}

输出:

Not yet.. [1 out of 2] conditions are failed
Success [1 of 2] => Expected 10 Actual 10 Good!
!! Failed [2 of 2] => Expected xxx Actual xx

 org.opentest4j.AssertionFailedError: expected: <true> but was: <false>
 Expected :true
 Actual   :false
于 2021-02-12T19:44:06.833 回答
-1

另一种选择是结合 lambda 表达式的可观察模式。你可以使用类似上面的东西。

public class MyTestClass {

    private final List<Consumer<MyTestClass>> AFTER_EVENT = new ArrayList<>();

    @After
    public void tearDown() {
        AFTER_EVENT.stream().forEach(c -> c.accept(this));
    }

    @Test
    public void testCase() {
        //=> Arrange
        AFTER_EVENT.add((o) -> {
            // do something after an assertion fail.
        }));

        //=> Act

        //=> Assert
        Assert.assertTrue(false);
    }
}
于 2018-09-17T11:36:47.060 回答