简体   繁体   English

JUnit 检查异常抛出的消息是 `stringA` 还是 `stringB`

[英]JUnit checking if the message thrown by an exception is either `stringA` or `stringB`

In my code I have some pattern like (I tried to simplified as much as possible):在我的代码中,我有一些类似的模式(我试图尽可能地简化):

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import java.util.Set;

public void funcSubSet() {
   final Set<String> setA = new HashSet<>(Arrays.asList("a", "b", "c", "d"));
   final Set<String> setB = new HashSet<>(Arrays.asList("a"));
   Preconditions.checkArgument(setB.constainsAll(setA),
                               "The strings %s are present in setA but not in setB",
                               Joiner.on(", ").join(setA.stream()
                                                   .filter(Predicate.not(setB::contains))
                                                   .iterator())
                               );
}

Basically, this checks if setA is fully contained in setB .基本上,这会检查setA是否完全包含在setB中。 If not, throws an exception and prints the elements that are in setA and not be in setB (separated by a comma and a space).如果不是,则抛出异常并打印 setA 中但不在setA中的setB (以逗号和空格分隔)。 When I test it, the problem is that it output the strings not contained in setB in different order sometimes and the following test case fails occasionally.当我测试它时,问题是它 output setB中未包含的字符串有时会以不同的顺序排列,并且以下测试用例偶尔会失败。

assertThrows(IllegalArgumentException.class,
             () -> funcSubSet()),
             "The strings b, c, d are present in setA but not in setB")

Sometime the output is like: "The strings d, b, c are present in setA but not in setB".有时 output 就像:“字符串 d、b、c 存在于 setA 中,但不存在于 setB 中”。

How do you I make it agnostic of the order?你如何让它与订单无关? How can I tell hasMessage() or any other assertion that I accept more than one string?我如何告诉hasMessage()或任何其他断言我接受多个字符串? I checked and couldn't find anything.我查了一下,找不到任何东西。

I use JUnit 5!我用的是JUnit 5!

If you can provide the sets to check from outside in your test (which I would recommend for a good code design and high testability), you can provide a java.util.LinkedHashSet<E> instead of a HashSet for the test.如果您可以在测试中提供要从外部检查的集合(我建议这样做以获得良好的代码设计和高可测试性),则可以提供java.util.LinkedHashSet<E>而不是HashSet进行测试。 This class ensure the iteration order to be in the order of first insertion, so you get a predictable outcome.这个 class 确保迭代顺序是第一次插入的顺序,所以你得到一个可预测的结果。

If you cannot choose the actual Set implementation for your test, I would write the test a bit different:如果您不能为测试选择实际的Set实现,我会编写一些不同的测试:

import org.junit.jupiter.api.Assertions;

//...

// expect permutation of:
//The strings b, c, d are present in setA but not in setB

Exception thrownException = Assertions.assertThrows(Exception.class, () -> funcSubSet());

String message = thrownException.getMessage();

Assertions.assertEquals("The strings ", message.substring(0, 12), "message start");
Assertions.assertEquals(" are present in setA but not in setB", message.substring(19), "message end");
String variables = message.substring(11,19);
Assertions.assertTrue(variables.contains(" b"), "contains b");
Assertions.assertTrue(variables.contains(" c"), "contains c");
Assertions.assertTrue(variables.contains(" d"), "contains d");

With Assertions.assertThrows you could also expect a fixed String and work with the caught exception for further details.使用Assertions.assertThrows ,您还可以期待一个固定的 String 并处理捕获的异常以获取更多详细信息。 org.junit.jupiter.api.Assertions is part of JUnit and does not need 3rd party dependencies like AssertJ. org.junit.jupiter.api.Assertions是 JUnit 的一部分,不需要像 AssertJ 这样的第三方依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM