我有实用方法来处理一些文本.处理方式由enum Mode决定.在编写单元测试来涵盖此方法时,我必须添加哑enum元素,以便将switch陈述的default部分包含到测试中.默认部分是我对enum由新元素扩展且此新元素未添加到switch声明的情况的判断,这意味着该新元素将不可能处理.如果我删除哑元素并try 使用null,那么我会得到NPE和Java甚至不会输入switch声明-当您将null用于switch声明时,这是正常行为.

The question:有没有方法可以避免在单元测试中添加哑enum元素,但仍然覆盖switch陈述的default部分?

为了清晰起见,添加了:Java 17、JUnit Jupiter 5、日食代码覆盖工具

Code

abstract class LineBreaker {

    public enum Mode {
        LAST_SPACES,
        LAST_CHARS,
        DUMMY
    }

    public static String process(
        final String text,
        final LineBreaker.Mode mode,
        final int amount
    ) {
        switch (mode) {
            case LAST_SPACES : {
                // blah blah create `processingResult`
                return processingResult;
            }
            case LAST_CHARS : {
                // blah blah create `processingResult`
                return processingResult;
            }
            default :
                throw new IllegalStateException(
                    "Processor for " +
                        LineBreaker.class.getSimpleName() + "." +
                        LineBreaker.Mode.class.getSimpleName() + "." +
                        mode.name() +
                        " not implemented"
                );
        }
    }

}

Unit test

@Test
void testLineBreakerException() {
    assertThrows(
        IllegalStateException.class,
        () -> LineBreaker.process( "Dog", LineBreaker.Mode.DUMMY, 10 ),
        "Expected " + IllegalStateException.class.getSimpleName()
    );
}

Unit test without additional dummy enum element

Unit test without additional dummy enum element

Code coverage without additional dummy enum element

Code coverage without additional dummy enum element


Unit test with additional dummy enum element

Unit test with additional dummy enum element

Code coverage without additional dummy enum element

Code coverage without additional dummy enum element

推荐答案

You don't need to create or extend the existing enum Mode. You just need to mock this enum with Mockito.
For this, you can use Mockito version 5 or later, which support mockito-inline as the default mockmaker. This will support mocking static method easily.

测试实现组:"org. mockito",名称:"mockito-core",版本:"5.11.0"

The strategy is to create a mock enum UNSUPPORTED. Use Mockito.mockStatic to mock the static method values() of the enum, and return the existing values plus the mock enum UNSUPPORTED.
Then this mock UNSUPPORTED enum would trigger the default path of your switch-case statement, which allow you to perform the assertion easily.

代码片段


import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doReturn;

public class SOEnumQuestionTest {

    public enum Mode {
        LAST_SPACES,
        LAST_CHARS
    }

    public static String process(final Mode mode) {
        switch (mode) {
            case LAST_SPACES : {
                return "processing last spaces";
            }
            case LAST_CHARS : {
                return "processing last chars";
            }
            default :
                throw new IllegalStateException("Processor not implemented");
        }
    }

    @Test
    public void testProcessWithDefaultSwitchCase() {
        try (MockedStatic<Mode> dummyModeMockedStatic = Mockito.mockStatic(Mode.class)) {
            final Mode UNSUPPORTED = Mockito.mock(Mode.class);
            // We want to give the mocked enum in the last position of the enum values list
            // E.g: Enum has 2 values -> our mock UNSUPPORTED enum index is 2
            doReturn(2).when(UNSUPPORTED).ordinal();
            dummyModeMockedStatic.when(Mode::values)
                    .thenReturn(new Mode[]{
                            Mode.LAST_SPACES,
                            Mode.LAST_CHARS,
                            UNSUPPORTED});

            Throwable expectedException = assertThrows(IllegalStateException.class, () -> SOEnumQuestionTest.process(UNSUPPORTED));
            assertEquals("Processor not implemented", expectedException.getMessage());
        }
    }
}

Java相关问答推荐

使用json参数通过单击jSP文件中的按钮来运行server时出现问题

使用Apache Poi MQLSlideShow,在XSLFTable表中,我们可以在文本段落后面的每个单元格中包含圆角矩形吗?

即使我正在使用并发方法,使用Javascript的应用程序也会继续冻结'

缩小画布比例后更改滚动窗格的内部大小

Java inline Double条件和值解装箱崩溃

XPages-在第二次点击按钮之前延迟

FALSE:它应该在什么时候使用?

我无法获取我的Java Spring应用程序的Logback跟踪日志(log)输出

Jakarta CDI强制bean构造/注册遗留事件侦听器

如何使用SpringBoot中的可分页对整数作为字符串存储在数据库中时进行排序

第三方Jar pom.xml

如何让JavaFx应用程序识别依赖项?

Arrays.hashcode(int[])为不同的元素提供相同的散列

我的Spring Boot测试显示&IlLegalStateException:无法加载某事的ApplicationContext.

使用Jackson库反序列化json

垃圾收集时间长,会丢弃网络连接,但不会在Kubernetes中反弹Pod

如何创建模块信息类文件并将其添加到JAR中?

插入中的JOOQ序列,设置为VS值

组合连接以从两个表返回数据

java.exe如何执行java源代码?