Junit如何检查字符串是否等于两个字符串中的一个?

22

这似乎是一个非常简单的问题,但我就是想不出来。

我只是想要断言一个字符串是否等于"string1"或者"string2"。

这是我尝试过的,但显然都不起作用。

assertEquals(d.getFormType(), "string1") || assertEquals(d.getFormType(), "string2");

assertEquals(d.getFormType(), "string1" || "string2");
6个回答

32
我建议您使用Hamcrest 匹配器。 它们通过JUnit的assertThat()集成,但是您还需要下载和安装hamcrest-all.jar

使用Hamcrest,您可以像这样解决问题:

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

assertThat(d.getFormType(), isOneOf("string1", "string2"));

如果无法安装Hamcrest,另一个选择是使用正则表达式:

assertTrue(d.getFormType().matches("(string1|string2)"));

这种方式比将两个equals()语句组合在一起更短,而且更易读:

String actual = d.getFormType();
assertTrue("string1".equals(actual) || "string2".equals(actual));

我希望有人能够发布Matchers的示例。我看了这个,但是无法弄清楚。 - Catfish
是的,它们工作得非常好,并在不匹配时提供良好的诊断信息。 - ᴇʟᴇvᴀтᴇ
当尝试导入org.hamcrest.Matchers.*时,它无法解析,因此isOneOf无法工作。我正在使用junit 4.10。 - Catfish
1
抱歉,您需要单独下载并安装Hamcrest jar。JUnit仅提供了Hamcrest的最基本框架 - 只足以支持集成。 - ᴇʟᴇvᴀтᴇ
这是一个艰难的决定,我选择了他的答案,因为我使用的方法可以指定消息。你的答案是我的第二选择,因为我喜欢你展示的其他解决问题的方式。不过我都给你们点了赞。 - Catfish
显示剩余4条评论

22
你可以使用 assertTrue()
assertTrue(d.getFormType().equals("string1") ||
           d.getFormType().equals("string2"));

或者使用扩展版本,在失败时提供更多信息:

assertTrue("Unexpected value for d.getFormType(): " + d.getFormType(),
           d.getFormType().equals("string1") ||
           d.getFormType().equals("string2"));

第二个代码容易出现NPE,而且由于该方法始终返回两个可能的值中的一个,因此消息可能包含与测试不同的字符串。 - Aaron Digulla
@AaronDigulla,关于NPEs的问题,请您参考此问题的已接受答案:https://dev59.com/5mkw5IYBdhLWcg3wbqKZ。至于参数值更改,这只是你猜测的。该方法似乎是一个查询方法,并且应该在调用次数多少的情况下返回相同的值(前提是没有调用任何中间对象修改方法,这在这里不是这种情况)。 - hmjd
1
早期NPE的问题在于它经常会让你在一长串代码中遇到错误,而不知道其中哪个位置导致了NPE。在这里,如果assertTrue()能够执行到,它会告诉你result是null。 - Aaron Digulla
2
Hamcrest 更适合这种情况,因为它的断言简短易读,并在失败时提供诊断信息。请参见 @aetheria 的回答。 - Kkkev
这种方法的缺点是,如果条件失败,你将看不到原因。你只能看到条件为假。 - Richard Jessop

4

断言类没有直接实现你想要的功能。但是你可以使用 assertTrue 并检查任何条件来实现。

assertTrue("string1".equals(d.getFormType()) || "string2".equals(d.getFormType()))

1
这很好。它非常易读,并且解决了NPE问题。 - Dawood ibn Kareem

1

怎么样?

Assert.assertTrue("msg", Arrays.asList("string1", "string2").contains(searchString));

如果失败,我会更新消息以便成为一个友好的信息。


0

我不知道有没有一个确切的JUnit风格来做这个,但是我会做一些更简单的事情来解决:

boolean stringEquals = false;
if ("string1".equals(d.getFormType()) || "string2".equals(d.getFormType())) {
    stringEquals = true;
}
assertTrue(stringEquals);

0

你的问题没有意义。单元测试总是有相同的结果 - 它们不是随机的,或者说,它们不应该是随机的。这就是为什么 JUnit 不支持交替结果的原因。

尝试找到一种设置测试的方法,使输出不会改变。

如果真的不可能,那么你的代码或者至少它的设计可能存在问题。

尝试修复这个问题。

如果你真的无法解决,那么可以使用:

boolean valid = ....some complex check...
assertTrue( valid );

[编辑] 为了同时测试多个值,您可以使用以下技巧:

String[] values = ...;
assertEquals( "0:...\n1:...",  "0:" + values[0] + "\n" + "1:" + values[1] ... );

即将所有值放入一个长字符串中,然后检查整个字符串。大多数IDE都会在两个文本编辑器并排显示差异,因此任何不匹配都很容易看到,而文本中的小提示(0:等)将告诉您错误的确切位置。


我想测试这个输出,因为我正在传递一个逗号分隔的字符串,并通过逗号进行拆分。我想测试我的方法能够正确处理逗号分隔的字符串。 - Catfish
然后,这甚至更没有意义。它应该始终返回相同的值。你需要的是 and 而不是 or。请查看我的编辑。 - Aaron Digulla
不,你错了。我正在设置一个字符串 string1,string2。在我的方法中,我将该字符串拆分并搜索 string1string2,然后将结果组合并返回。因此,我想通过我的 JUnit 测试验证表单类型是 string1 或 string2 中的任意一个。明白吗? - Catfish
1
不行,这看起来像是一个集成测试:你测试的太多了。尝试将该方法拆分为较小的部分,以便您可以独立测试“拆分逗号分隔值”的功能。 - Aaron Digulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接