如何从静态初始化块对逻辑进行单元测试?

时间:2018-10-20 00:20:20

标签: java spring

我在一个类中有一个私有的静态最终列表,该列表是通过静态初始化块进行初始化的。

private static final List<String> list;

static {
    list = //lambda expression
}

我如何继续为诸如此类的东西编写测试?这是一个永远不会改变的字符串列表。

2 个答案:

答案 0 :(得分:0)

您要在这里测试什么?列表的内容是否完全符合预期?如果是这样,请首先使您的变量可见以进行测试。 (另一种选择是使用反射来获取列表的内容,但是这种方法更简单)。另外,您发布的代码中有错误。您正在尝试在非静态块中初始化静态变量。我建议您在初始化类本身时,一旦列表被初始化一次,就切换到 static 块,无论您创建了多少这种类型的对象。

enum Example {
    A,
    B,
    C
}

@VisibleForTesting static final List<String> list;
static {
    list = Arrays.asList(Example.values()).stream()
            .map(Example::name)
            .collect(Collectors.toList());
}

您可以忽略@VisibleForTesting注释。这很高兴,它指示您将范围更改为package-private以便测试该变量。我建议使用AssertJ,因为它具有一些不错的测试方法。例如,您可以像这样在测试中声明列表的内容:

assertThat(Foo.list).containsExactlyInAnyOrder("B", "A", "C");

如果要按顺序声明内容,可以使用containsExactly("A", "B", "C")方法。如果您的列表是动态生成的,但您不知道其内容,则可以使用hasSize(3)方法断言其大小符合预期。

答案 1 :(得分:0)

从单元测试的角度来看,静态状态是有问题的。这是Spring使用依赖注入的原因之一!

您能做的最好的事情是编写一个单元测试,以检查是否已将静态变量初始化为预期状态。

您说:

  

这是一个永远不会改变的字符串列表。

这取决于您对“永不”的意思:

  • 您(几乎)永远不能保证某些事情永远不会改变。您可能需要更改代码以适应新要求。

  • 如果您可以枚举期望值并将其硬连线到单元测试的代码中,就可以了。当然,如果您的代码更改,则可能需要更改单元测试。但这也没关系。

  • 如果您要测试的值可能取决于环境或某些先前初始化的结果,那么您就会遇到大问题。根据JLS,类初始化只能在JVM的生存期内执行一次。

    在这种情况下,“解决方案”是:

    • 完全摆脱静电;例如将其替换为DI。
    • 将其重组为可测试的;例如使用可以测试的静态方法进行操作。
    • 在不同的JVM中多次运行整个测试套件 ,对于每个不同的初始化路径都运行一次。
    • 不要在单元测试中测试初始化​​。