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