我有下面的代码片段,我不确定如何用单元测试覆盖default子句。
public Block solve(String str) {
try {
final BlockType blockType = BlockType.valueOf(str);
switch (blockType) {
case TEXTBLOCK:
return ...
case IMAGEBLOCK:
return ...
default:
return null;
}
} catch (final IllegalArgumentException e) {
return null;
}
}
@AllArgsConstructor
public enum BlockType {
IMAGEBLOCK("imageBlock"),
TEXTBLOCK("textBlock");
private String value;
}
注意:我有一个限制,即solve
方法中的参数必须是String
类型。另外,我不想仅仅为了测试目的而在枚举中添加任何虚拟值。
2条答案
按热度按时间pgky5nke1#
如果默认情况确实是不可访问的(就像您的情况一样),您有两个选择:
1.你就放下吧。
1.抛出错误而不是返回
null
:在这种情况下,你很快就知道,如果你添加一个额外的
BlockType
枚举值,而不是一些虚假的NullPointerExceptions
发生在远离switch
的地方,有些东西就不起作用了。关于你最初的问题:如果不大量修改代码,就无法测试它。但对于像这种默认标签的“安全网”来说,这并不罕见。
6ovsh4lw2#
在您的示例中,有一种方法可以覆盖
default
案例。但确实很恶心。首先,我们需要理解为什么示例中的
default
案例没有标记为无法访问的代码。这是JLS 13.4.26中规定的enum
类演化规则的逻辑结果。这说明向现有的enum
添加额外的常量不会破坏二进制兼容性。因此,虽然在你的例子中的
default
分支在代码被编译的时候是不能有效地访问的,但是如果稍后在enum
中添加另一个常量,它就可以变得可访问。而且Java编译器 * 不会 * 将default
分支标记为无法访问的代码……你也看到了!所以......在示例中获得
default
分支的100%单元测试覆盖率的“讨厌”方法就是模拟代码的演变。编写enum
类的另一个版本,其中包含一个额外的常量,然后编写一个单元测试,将该常量提供给带有switch
语句的代码。另外,我不想仅仅为了测试目的而在枚举中添加任何虚拟值。
不是这样的我们正在做的是模拟
enum
的(假设的)* 未来 * 版本。当前版本没有额外的常量。如何使其在典型的单元测试框架和典型的Java构建工具的上下文中工作,留给读者作为练习。
这样做好吗?IMO不!最好是承认它是(通常)不值得去极端“实现”100%的覆盖率.事实上,如果您的代码中有一个“这永远不应该发生”的情况,那么在测试期间尝试使该情况实际发生是没有价值的。
但是......如果你的应用程序的设计目标是 * 处理 *
enum
的演变,那么实现对无法访问的default
情况的覆盖可能是合理的。然而...在这种情况下返回
null
确实是个坏主意;查看评论和上面的答案,了解原因,以及你可以做些什么。