模拟新的枚举值以测试 switch 中的默认情况

问题描述 投票:0回答:1

我正在尝试在检查枚举的开关中测试默认情况。我看过一些帖子并找到了这个解决方案:

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
}

任何人都可以向我解释我做错了什么吗?

enums switch-statement java-11
1个回答
0
投票

如果需要测试使用枚举的 switch 语句中的默认情况,可以通过使用 Mockito 创建枚举的模拟来实现。该模拟可以模拟实际枚举中不存在的枚举值,从而强制开关达到默认情况。

这是分步指南:

逐步解决方案:

  1. 为不支持的枚举值创建模拟

使用 Mockito 创建枚举的模拟。该模拟将表示不支持的值,该值不属于实际枚举。

  1. 模拟values()方法:

使用Mockito中的MockedStatic来模拟枚举的values()方法。这允许您将模拟枚举值包含在 value() 返回的数组中,从而模拟意外枚举值的存在。

  1. 调用被测方法

如果您正在测试的方法是私有的或受保护的,请使用反射来调用它。这样,您可以直接将模拟枚举值传递给方法并强制 switch 语句命中默认情况。

  1. 断言预期异常:

使用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);
            });
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.