除了测试之外,如何为所有调用者创建一个Java方法?

时间:2013-06-26 19:46:00

标签: java testing private public

我有一个Java类,它有一个私有方法来计算一些默认值;和两个构造函数,其中一个省略了该值,并使用私有方法获取默认值。

public class C {
    private static HelperABC getDefaultABC() {
        return something; // this is a very complicated code
    }

    public C() {
        return C(getDefaultABC()); 
    }

    public C(HelperABC abc) {
        _abc = abc;
    }
}

现在,我正在尝试为这个类编写测试,并且想测试BOTH构造函数;第二个构造函数传递默认值。

现在,如果getDefaultABC()是公开的,那将是微不足道的:

// We are inside class test_C
// Assume that test_obj_C() method correctly tests the object of class C
C obj1 = new C();
test_obj_C(obj1);

HelperABC abc = C.getDefaultABC();
C obj2 = new C(abc);
test_obj_C(obj2);

但是,因为getDefaultABC()是私有的,我无法从测试类中调用它 !!!。

所以,我被迫写了一些愚蠢的东西:

// Assume that test_obj_C() method correctly tests the object of class C
C obj1 = new C();
test_obj_C(obj1);

// here we will insert 20 lines of code
// that are fully copied and pasted from C.getDefaultABC()
//   - and if we ever change that method, the test breaks.
// In the end we end up with "HelperABC abc" variable
C obj2 = new C(abc);
test_obj_C(obj2);

有没有办法解决这个难题(理想情况下,通过某种方式将C.getDefaultABC()标记为除了类test_C之外的所有人除外)除了简单地将方法从私有更改为公共?

4 个答案:

答案 0 :(得分:4)

There's no equivalent to friend in Java. (that link from T I above)我这样做的方法是将方法声明为包保护,如下所示:

static HelperABC getDefaultABC()

这样做,只要测试类与getDefaultABC()位于同一个包中,就允许测试代码调用C。当然,这会让同一个包中的任何其他类都调用它,但我认为你将不得不忍受这一点,这是你不用反射就可以做到的最好的。但是如果你使用反射,那么每个其他类也可以使用反射来调用getDefaultABC(),因此它几乎就像“易受攻击”一样。我只是让它受到包保护,所以至少它比使用反射更具可读性。


我会告诉你怀疑的好处,并说你可能继承了这段代码,目前还不能测试。您需要做的就是让getDefaultABC()进入可测试状态。测试甚至不一定要好,你只需要一些信心。一旦你对测试有了信心,你会发现getDefaultABC()中的代码与获取默认ABC无关。较低级别的抽象,如连接到数据库或其他任何东西。您需要识别该代码并将其提取到自己的类中。然后,为提取的类编写更好的测试。

如果您将此代码重构为非常干净的状态,您应该能够摆脱不良测试并将getDefaultABC()恢复到private状态。 private意味着内部实施。您不应该直接测试内部实现。

答案 1 :(得分:2)

不是绝对干净,但您可以使用反射在测试中调用私有方法 对我而言,使用反射似乎更好,因为它是非侵入性的,您不必仅仅因为测试而更改方法访问修饰符。

这样的事情:

    Method method = obj1.getClass().getMethod("getDefaultABC");
    method.setAccessible(true);
    HelperABC abc = (HelperABC) method.invoke(obj1);

答案 2 :(得分:1)

使方法受保护

protected static HelperABC getDefaultABC() {
        return something; // this is a very complicated code
    }

然后扩展测试类:

public class testC extends C{
   ...
}

答案 3 :(得分:0)

如果你可以允许包级别访问,通过遵循SUT和测试类在同一个包(不同的源文件夹)上的测试类的相同包规则,你可以使它更干净恕我直言。

相关问题