关于java:在测试时使用反射破坏封装是多么邪恶?

How evil is it to use reflection to break encapsulation when testing?

我正在测试3个新类,这些类生成3个序列化为数据库的对象集合。 其中一个类具有硬编码的字符串数组。 3个集合的结尾大小与字符串数组相同,集合中的每个对象都根据数组中的字符串获取名称/标记。

我的一个测试是端到端测试,它将尝试制作所有三个集合。 我想访问用于测试的字符串数组,但它是私有的。 我看到三种可能的方法来解决这个问题:

  • 使其受到保护< - Office策略是不为了测试而修改代码设计。
  • 将数组复制到测试类< - 现在必须在两个位置维护数组更改。噢。
  • 使用反思来窥视私人< - 这有效,但它或多或少比其他选择更邪恶?

你能想到第四种方式吗? 是否有充分理由不使用反射?


这实际上取决于你的测试试图运用什么。通常,如果您正在测试代码的内部实现细节,那么您可能在测试时做错了。毕竟,您的测试应该是执行代码的可观察效果,??而不是实现细节。执行实现细节的测试很脆弱(需要在实现更改时进行更新),并且通常只是实现的副本。此外,因为它们反映了实现,所以实现中的错误也可能反映在测试中,因此这些测试通常具有可疑的价值。

更好的方法是使用一个接口来表示您的数据库对象,并使用模拟框架(如mockito)来验证您期望的数据是否写入数据库并从数据库中读取,而不检查代码的内部结构在将数据写入数据库之前将数据存储在内部。

此外,就不为测试编写不同的代码而言......通常,最好不要在生产代码中使用仅测试方法。但是,重构代码使其更加模块化(因此更易于测试),这是一种通常很好的编码实践。


变量本身应保持私有,但您可以添加具有默认(包私有)访问权限的getter。

如果测试代码位于同一个包中。这马上解决了这个问题。

如果其他软件包的测试代码需要访问此getter,则必须编写以下格式的样板:

被测试的类具有私有字段和具有默认访问权限的getter:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyClass {

    private Object someData;

    // you should research the usage of these or similar annotations
    // they will help your IDE to catch improper usage of test-only methods
    //@com.google.common.annotations.VisibleForTesting
    //@org.jetbrains.annotations.TestOnly
    Object getSomeData() {
        return someData;
    }

}

测试代码包含一个帮助器,它将getter公开为public,因此可以从其他包中的测试中使用它:

1
2
3
4
5
6
7
public class MyClassTestHelper {

    public static Object getSomeData(MyClass instance) {
        return instance.getSomeData();
    }

}

您还应该看看如何测试具有私有方法,字段或内部类的类? (您的问题甚至可以被认为是重复的)和注释,以使私有方法仅对测试类公开。