我正在尝试在检查枚举的开关中测试默认情况。我看过一些帖子并找到了这个解决方案:
int nValues = EnumType.values().length;
try (MockedStatic<EnumType> mocked = mockStatic(EnumType.class)) {
val UNSUPPORTED = mock(EnumType.class);
doReturn(nValues).when(UNSUPPORTED).ordinal();
doReturn(nValues).when(UNSUPPORTED).getValue();
doReturn("UNSUPPORTED").when(UNSUPPORTED).name();
mocked.when(EnumType::values).thenReturn(new EnumType[] {
EnumType.A,
EnumType.B,
EnumType.C,
EnumType.D,
UNSUPPORTED});
assertThatThrownBy(() -> mapper.callSwitch(UNSUPPORTED))
.isInstanceOf(CustomException.class);
}
但是这给了我 switch 语句上的以下错误
Java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
对此答案的评论之一https://stackoverflow.com/a/7233572/2696646似乎描述了我的问题的解决方案,但据我所知,我正是这样做的。
这是我的枚举和开关:
public enum EnumType{
A(0),
B(1),
C(2),
D(3);
}
switch (status) {
case A:
return "aaaa";
case B:
return "bbbb";
case C:
return "cccc";
case D:
return "dddd";
default:
// throw some custom exception
}
任何人都可以向我解释我做错了什么吗?
如果需要测试使用枚举的 switch 语句中的默认情况,可以通过使用 Mockito 创建枚举的模拟来实现。该模拟可以模拟实际枚举中不存在的枚举值,从而强制开关达到默认情况。
这是分步指南:
逐步解决方案:
使用 Mockito 创建枚举的模拟。该模拟将表示不支持的值,该值不属于实际枚举。
使用Mockito中的MockedStatic来模拟枚举的values()方法。这允许您将模拟枚举值包含在 value() 返回的数组中,从而模拟意外枚举值的存在。
如果您正在测试的方法是私有的或受保护的,请使用反射来调用它。这样,您可以直接将模拟枚举值传递给方法并强制 switch 语句命中默认情况。
使用assertThrows确保方法在遇到不支持的枚举值时抛出预期的异常。
示例代码:
enum ExampleEnum {
A, B, C, D
}
测试方法:
@Test
void testMethodWithUnsupportedEnum() throws NoSuchMethodException {
try (MockedStatic<ExampleEnum> mockedStatic = Mockito.mockStatic(ExampleEnum.class)) {
// Create a mock for the unsupported enum value
ExampleEnum UNSUPPORTED = Mockito.mock(ExampleEnum.class);
Mockito.when(UNSUPPORTED.ordinal()).thenReturn(99); // Set a high ordinal value
Mockito.when(UNSUPPORTED.name()).thenReturn("UNSUPPORTED");
Mockito.when(UNSUPPORTED.toString()).thenReturn("UNSUPPORTED");
// Mock the values() method to include the unsupported enum value
mockedStatic.when(ExampleEnum::values)
.thenReturn(new ExampleEnum[]{
ExampleEnum.A,
ExampleEnum.B,
ExampleEnum.C,
ExampleEnum.D,
UNSUPPORTED
});
// the params in getDeclaredMethod (): method name, and passe the param type in your method for exemple here our method have two params (String a, ExampleEnum exp)
//use reflection to access the method if it's not public
Method method = ExampleClass.class.getDeclaredMethod("methodUnderTest", String.class, ExampleEnum.class);
method.setAccessible(true);
// Assert that the default case throws the expected exception
assertThrows(InvocationTargetException.class, () -> {
method.invoke(null, "testValue", UNSUPPORTED);
});
}
}