将私有成员更改为默认值以进行测试

时间:2011-04-14 11:12:49

标签: java unit-testing

将私有类成员更改为默认(包访问)以测试其行为是否是个好主意?我的意思是测试用例应该在测试目录中,但在与测试成员的类相同的包中。

编辑:你们所有人都说实话。但是类经常有辅助私有方法。而这些方法可能很复杂,因此需要进行测试。这太糟糕了 - 测试公共方法以确保正确处理私有复杂方法。你不这么认为吗?

4 个答案:

答案 0 :(得分:9)

我通常更喜欢编写类和测试,以便针对公共API编写测试是有意义的。所以基本上我说如果你需要访问你的类的私有状态测试你可能已经太过参与了你的测试的那个类的内部..

答案 1 :(得分:1)

不,不是。因为更改测试对象可能会更改结果。如果您确实需要在测试期间调用私有成员或方法,则添加访问器会更安全。这仍然改变了课程,但风险较低。例如:

private void method() { /* ... */ }

// For testing purpose only, remove for production
@Deprecated  // just another way to create awareness ;)
void testMethod() {
   method();
}

好的 - 如果您需要测试私有方法,还可以使用另一个解决方案:您可以使用反射和实例化API调用任何方法。

假设我们有:

public class SomeClass {
  private Object helper(String s, String t) { /* ... +/ }
}

然后我们可以像

那样测试它
@Test public void testHelper() {
   try {
     SomeClass some = new SomeClass();
     Method helperMethod = some.getClass().getDeclaredMethod("helper", String.class, String,class);
     helperMethod.setAccessible(true);
     Object result = helperMethod.invoke(some, "s", "t");
     // do some assert...

   catch(Exception e) {
     // TODO - proper exception handling
   }
}

答案 2 :(得分:0)

我理解你需要测试私有方法的意思,我也明白为什么人们只说测试公共方法。我刚刚遇到一些遗留代码,它们有很多私有方法,其中一些是公共方法调用的,但有些是线程,或者是线程调用,它们在构造对象时被启动。由于代码充满了bug并且没有任何注释,我被迫测试私有代码。 我使用这种方法来解决这个问题。

   MainObject.cs
    class MainObject
    {
        protected int MethodOne();    // Should have been private.
        ....
    }
    TestMainObject.cs
    class ExposeMainObject : MainObject
    {
        public int MethodOne();
    }
    class TestMainObject
    {
        public void TestOne()
        {
        }
    }

由于测试对象没有发货,我看不出有问题,但如果有,请告诉我。

答案 3 :(得分:0)

测试胜过隐私修饰符。真的,因为过多而导致的错误的频率是多少?#34;方法的可见性?与未完全测试的方法引起的错误相比?

如果Java有一个朋友"那将会很好。选项,就像C ++一样。但语言的限制永远不应成为不测试某事的借口。

迈克尔·费尔斯(Michael Feathers)在“有效地使用遗产守则”#34; (优秀的书),并建议这可能是一个想要被提取(并有公共方法)的子类的气味。

在我们的商店(约1M LOC),我们更换私人'使用' / TestScope /'作为一个指标,一个方法应该是有效的私人,但仍然可以测试。

试图规避私人'用反射是恕我直言的气味。它使测试更难以编写,阅读和调试,以保持“迷恋”。隐私,你无论如何都在努力。为什么要这么麻烦?