你应该如何为同一个接口的多个实现编写junit测试用例?

时间:2009-01-09 11:32:34

标签: java unit-testing junit

在提问之前,让我解释一下当前的设置:

我有一个服务接口,比如Service,还有一个实现,比如说ServiceImpl。此ServiceImpl使用其他一些服务。春天,所有服务都以bean的形式加载。

现在,我想为ServiceImpl编写junit测试用例。同样,我使用applicationContext来获取Service bean,然后在其上调用不同的方法来测试它们。

所有公共方法看起来都很好但是如何为私有方法编写测试用例?因为我们可能没有相同的私有方法用于不同的实现?

任何人都可以在这里帮助我编写测试用例的首选方法吗?

5 个答案:

答案 0 :(得分:5)

纯粹主义的回答是私人方法被称为有原因! ; - )

转过来问题:只给出(可公开访问的)界面的规范,在编写代码之前如何布置测试计划?该接口描述了实现它的对象的预期行为;如果在那个级别上无法测试,那么设计就会出现问题。

例如,如果我们是运输公司,我们可能会有这些(伪编码)接口:

CapitalAsset {
    Money getPurchaseCost();
    Money getCurrentValue();
    Date  whenPurchased();
    ...
}

PeopleMover {
    Weight getVehicleWeight();
    int    getPersonCapacitly();
    int    getMilesOnFullTank();
    Money  getCostPerPersonMileFullyLoaded(Money fuelPerGallon);
    ...
}

可能包含以下类:

Bus implements CapitalAsset, PeopleMover {
    Account getCurrentAdvertiser() {...}
    boolean getArticulated() {...}
    ...
}

Computer implements CapitalAsset {
    boolean isRacked() {...}
    ...
}

Van implements CapitalAsset, PeopleMover {
    boolean getWheelchairEnabled() {...}
    ...
}

在设计CapitalAsset概念和界面时,我们应该与财务人员达成协议,了解 CapitalAsset的任何实例应如何表现。我们会针对仅依赖 CapitalAsset编写测试;我们应该能够在BusComputerVan上运行这些测试,而不依赖于哪个具体类。同样适用于PeopleMover

如果我们需要测试与BusCapitalAsset的一般合同无关的PeopleMover的某些内容,那么我们需要单独的总线测试。

如果某个特定的具体类具有如此复杂的公共方法,以至于TDD和/或BDD无法干净地表达其预期的行为,那么,这又是一个有问题的线索。如果在具体的类中有私有的“帮助”方法,那么它们应该出于特定的原因;应该可以问一个问题“如果这个助手有缺陷,哪些公共行为会受到影响(以及如何)?”

对于合法的,固有的复杂性(即来自问题域),类可能适合具有辅助的私有实例,这些实例承担特定概念的责任。在这种情况下,辅助类应该可以单独测试。

一个好的经验法则是:

  

如果测试太复杂,那就太复杂了!

答案 1 :(得分:4)

私有方法应该通过类的公共接口来执行。如果你有多个相同接口的实现,我会为每个实现编写测试类。

答案 2 :(得分:1)

您已经编写了接口的多个实现,并希望使用相同的JUnit4-test测试所有实现。在下面的内容中,您将看到如何执行此操作。

还有一个示例,展示了如何为每个测试用例获取新实例。

示例代码 在开始解释之前,这里是java.util.list界面的一些示例代码:

public class ListTest {

  private List<Integer> list;

    public ListTest(List<Integer> list){
      this.list = list;
    }

    @Parameters
    public static Collection<Object[]> getParameters() {
      return Arrays.asList(new Object[][] {
        { new ArrayList<Integer>() },
        { new LinkedList<Integer>()}
      });
    }

    @Test
    public void addTest(){
      list.add(3);
      assertEquals(1, list.size());
    }
}

答案 3 :(得分:0)

我认为你应该分开测试用例。

首先测试调用接口的不同实现的类。这意味着你正在测试公共方法。

在此之后,您将在另一个测试用例中测试接口实现类。他们可以用反射来调用方法。

答案 4 :(得分:0)

我在http://www.artima.com/suiterunner/privateP.html

找到了一篇关于如何使用JUNIT测试私有方法的有趣文章

因此,我认为我们应该更喜欢通过测试公共方法来间接测试私有方法。只有在特殊情况下,我们才应该考虑测试私有方法。