私有方法

时间:2015-04-28 00:19:41

标签: java junit4

我读到了这个问题:How do I test a class that has private methods, fields or inner classes?似乎我可能有代码味道,但我的代码实际上很难重构。我创造的设计有什么问题。 我创建了一个委托类来处理一些行为,它有三种方法execute(Action); PopulateActionHandlers()executeActionhandlers(); 我的课程如下:

public class DelegateHandler{
    Map<Integer,ActionHandlers> handlerMaps;

    public execute(Action action){
        populateActionHandlers(action);
        executeActionHandlers();

    }//end of execute

    //This method can create and populate more than one handlers in handlerMap
    private populateActionHandlers(action){
        handlerMap = new LinkedHashMap<ActionHandlers>();
        if (action.isMultimode()){
            handlerMap.add(1,new handler(action.getabc()));
            handlerMap.add(2,new handler(action.getabc()-1));
        }else{
            handlerMap.add(1,new handler(action));
        }

    }//end of populateActionHandlers

    //This method can execute more than one handlers in handlerMap
    private executeActionHandlers(){
        for(ActionHandler actionHandler : handlerMap.values){
            actionHandler.executeAction();
        }

    }//end of executeActionHandlers
}

现在我想用JUnit测试populateActionHandlers()方法,我将其设为私有,因为不需要在此类之外公开它。如果我测试execute()方法,那么它将测试同时测试两个单元的populateActionHandlers()executeActionHandlers()方法,我想分别测试它们。设计(我认为)对我来说似乎没有问题,并且不允许任何问题但是我要么改变对方法的访问权限(并且只是为了测试它在我看来不合理,对吧?)或者使用反思(这是一个好主意,不知何时感觉不对,人们通常使用反射进行junit测试吗?)。所以唯一不能排除的是代码味道。但可能是我的代码窦并没有真正帮助我所以我想了解我是否可以改进这段代码。

1 个答案:

答案 0 :(得分:0)

不测试私有方法的建议不应该通过省略私有方法来阻止人们做一个奇怪的设计,而应该强制只测试具有明确语义的方法。

私人方法通常是技术助手。如果底层数据结构发生变化,它们的语义可能会发生变化,如果调用公共方法使用另一种算法来实现相同的目标,它们甚至可以被优化掉。

我会按照以下方式重写程序:

...
public execute(Action action){
    Map<Integer,ActionHandlers> handlerMap = populateActionHandlers(action);
    executeActionHandlers(handlerMap);
}
...

将一个函数的结果存储到私有字段只是为了从另一个函数中的这个字段中检索它不是线程安全的,而且难以维护。

然而,这种重构会破坏测试您示例的私有方法的所有(但不是写入)测试,因为接口已更改。如果您只测试了公共方法,那么在重构之后所有测试都是有效的。

我知道测试私有方法的情况很少。虽然测试私有方法通常是可以避免的,但我认为检查私有状态有时是比仅检查对象的公共状态更好的选择。这种检查可能不那么健全(原因如上),但公共状态往往是不完整的,很难断言。在这两种情况下,我都使用框架picklock,这使得人们可以方便地访问私有方法和字段。