Java中如何用单元测试覆盖switch case的不可达default分支
如何覆盖switch case中的default分支单元测试
问题场景
我有如下代码片段,不确定如何通过单元测试覆盖switch case中的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类型,且我不想为了测试给枚举添加虚拟值。
解决方案
核心思路是通过反射临时创建一个虚拟枚举实例,让BlockType.valueOf(str)能返回这个不属于现有枚举的实例,从而触发switch的default分支,且无需修改原有业务代码或枚举定义。
测试代码示例:
import org.junit.Test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import static org.junit.Assert.assertNull; public class YourClassTest { @Test public void testSwitchDefaultBranch() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, NoSuchFieldException { // 1. 获取原有枚举的values数组 Method valuesMethod = BlockType.class.getDeclaredMethod("values"); BlockType[] originalValues = (BlockType[]) valuesMethod.invoke(null); // 2. 构造新的枚举实例 Constructor<BlockType> constructor = BlockType.class.getDeclaredConstructor(String.class, int.class, String.class); constructor.setAccessible(true); // 构造一个名称为DUMMY的虚拟枚举,序号设为原数组长度,value随便填 BlockType dummyBlock = constructor.newInstance("DUMMY", originalValues.length, "dummy"); // 3. 临时替换枚举的values数组 Field valuesField = BlockType.class.getDeclaredField("$VALUES"); valuesField.setAccessible(true); BlockType[] tempValues = new BlockType[originalValues.length + 1]; System.arraycopy(originalValues, 0, tempValues, 0, originalValues.length); tempValues[originalValues.length] = dummyBlock; valuesField.set(null, tempValues); try { // 4. 调用solve方法,传入虚拟枚举的名称,触发default分支 YourClass yourClass = new YourClass(); Block result = yourClass.solve("DUMMY"); assertNull(result); // 验证default分支的返回值 } finally { // 5. 恢复原枚举数组,避免影响其他测试 valuesField.set(null, originalValues); } } }
说明
- 枚举的
valueOf方法是根据枚举名称(如TEXTBLOCK)匹配的,反射构造的虚拟枚举名称为DUMMY,因此传入"DUMMY"会返回这个虚拟实例。 - 必须在
finally块中恢复原枚举的values数组,否则会干扰其他依赖该枚举的测试用例。 - 这种方式完全符合你的要求:不修改业务代码、不新增枚举值、solve方法参数保持String类型。
内容的提问来源于stack exchange,提问作者ASHOK KUMAR
相关产品推荐
相关产品推荐

