使用反射API访问私有方法和变量是否很好?

问题描述:

我想在编写Junit测试用例时访问类的私有方法。使用反射API很好吗?某处我发现反射API很慢.P使用反射API访问私有方法和变量是否很好?

请给出建议。

+1

如果您需要访问您的Junit测试的私有方法,那么您的测试设计得不好或者测试的类是。所以,如果你有权访问这两者,然后重新考虑测试或测试类的结构。 – Tom

+1

访问私有方法,来自其他类的变量永远不是一个好主意 – Jens

+0

@Jens我应该怎么做才能在私有方法中写一个Junit –

你应该考虑一下你的设计。如果你必须考虑测试私有方法,你的类可能会做更多的事情,并在某些时候违反SRP。我强烈建议您创建一个职责较小的新课程。看起来你的班级看起来不太好,所以削减它应该没问题。

你可以使用反射测试你的私有方法,但仍然 - 这不是好的方法。

+0

为什么我得到一个downvote? – ByeBye

根据正常的编程流程对java和junit测试是一种不好的做法,尤其是需要验证被测系统(您的类)的方式与您将在应用中使用它的方式相同。反思打破类封装。

如果您想测试私有方法,您需要完全重新安排开发工作流并使用测试驱动开发。示例如何测试私有方法正确tdd方式。假设我们有A类和测试它:

class A { 

    public int calculate() { 
     //very complex code 
     // 50+ lines of code 
    } 

} 

class ATest { 

    public void shouldCalculateComplexThing() { 
     A a = new A(); 
     int answer = a.calculate(); 
     Assert.assertEquals(answer, 42); 

    } 

} 

我们提到calculate()方法是太大了在第一看就明白,我们需要 重构它:

class A { 

    public int calculate() { 
     return calculateFirstPart() + calculateSecondPart(); 
    } 

    private int calculateFirstPart() { 
     //code 
    } 
    private int calculateSecondPart() { 
     //code 
    } 

} 

因为我们有测试它我们已经有相同的答案42,但我们更改了代码并引入了私有方法 ,我们不需要测试它,因为它们通过方法calculate()进行了测试。这是测试私有字段,方法和其他类实现细节的正确方法tdd

+0

所以一个超级有才华的测试者出现并发现你需要更多的单元测试。也许他是个数学家,所以他比你知道的要好,你忽视了一个特定的,有趣的算术条件。 (S)他写了更多的测试用例,确实在“calculate()”中有问题。也许不是一个例外,但它只是默默地返回一个错误的值。如果问题存在于calculateFirstPart()或calculateSecondPart()中,现在如何决定?如果您首先测试了私有方法,那么您可能已经拥有了这些信息。单元测试正在测试尽可能最小的部分! – weiglt

+0

@ weiglt尽可能小的部分它不是实现细节。测试私有方法限制我们进行重构,因为测试知道我们如何在类中做事,而不是只验证公共合约的正确输出。当代码非常复杂时,我们可能会将这些复杂的方法重构为不同的类并单独测试这些类。 – fxrbfg

理想情况下,您不应该在单元测试中访问任何隐藏变量。但是如果你必须这样做,那么有一种可能性是使用软件包保护的可见性(无修饰符)。这样,你的单元测试就可以读取/写入字段,只要它与被测试的类位于同一个包中即可。

是的,这种方法非常好,我想大多数进行彻底的单元测试的项目并不罕见。反射API可能是为了这个目的而创建的。

为什么你担心反射API速度缓慢?它只会减慢测试速度,对于正常运行时的用户无关紧要。但是,如果您的测试由于反射API访问而变得太慢,那么请升级您的开发硬件。即使你以数百万的数量进行了大量的模块测试,我也不认为它会成为一个问题。

只是不要更改您的实际非测试程序源代码,如将所有内容更改为公开,因为您要测试它。这实际上是一件非常糟糕的事情。你想要一个干净的API和干净的类,所以你不想暴露一切。

测试可以并且通常会对您的软件体系结构产生影响,如鼓励更松散耦合的体系结构以及因此使用体系结构模式(如依赖注入)。但是,测试不能定义您的API。API应该是你认为它应该是的,而不是单元测试需要的东西(这可能会将所有东西都设置为公开,这显然不是语言设计者所期望的,当他们引入修饰符(如私有或受保护的)时)。

但是,在后来的测试阶段,像系统测试一样,显然不再需要使用反射API,因为您只需触发代码的普通公共API并观察/检查响应。您通常不希望进入代码并在此测试阶段检查其他内容。但是,可能会有某些情况,例如检查标志或非常关​​键的值,您要仔细检查。