3

我已经开始阅读 Spring in Action 这本书。

我不知道我认为我怀疑的 JUnit。

有一个代码片段,作者参考并说很难测试:

package com.springinaction.knights;

public classDamselRescuingKnight implements Knight {

    private RescueDamselQuest quest;

    public DamselRescuingKnight() {
       quest = new RescueDamselQuest();
    }

    public voidembarkOnQuest() throwsQuestException {
       quest.embark();
    }
}

作者说:

为 DamselRescuingKnight 编写单元测试非常困难。在这样的测试中,您希望能够断言在调用骑士的登船任务() 时调用了任务的登船() 方法。但是这里没有明确的方法来实现这一点。不幸的是,DamselRescuingKnight 将保持未经测试。

作者这是什么意思?

为什么这里的代码很难测试?

4

4 回答 4

8

我最初的想法是很难测试,因为“RescureDamselQuest”对象是在构造函数中初始化的。这使得例如插入模拟对象变得困难。模拟对象将帮助您测试是否在“RescueDamselQuest”对象上调用了 board() 方法。

解决这个问题的更好方法是在构造函数中包含一个参数(通常我更喜欢这种方法):

public DamselRescuingKnight(RescueDamselQuest quest){
   this.quest = quest;
}

或者添加一个设置器:

public void setDamselRescuingKnight(RescueDamselQuest quest){
   this.quest = quest;
}
于 2013-03-13T13:44:58.037 回答
2

我给出的一个常见示例是假设您想要打开一个文件,解析它,然后取出一个数据类。大多数人会做类似的事情:

Data openAndParse(String filename) {
  ...openFile
  ...parse
}

通过这种方式,文件打开方法和解析高度耦合并且难以测试。如果您在打开和解析中遇到问题,是解析还是打开?

通过编写 JUnit 测试,为了简单起见,您被迫执行类似...

BufferedReader openFile(String filename) {
  ...open file and return reader
}

Data parse(BufferedReader input) {
  ...parse and return data
}

JUnit 引导我们找到一个更有凝聚力的解决方案。我们简单地通过创建一个字符串、构造一个 StringReader 和一个 BufferedReader 来编写 JUnit 测试。你猜怎么着?非常相似,我们现在可以使用 parse 来接受来自各种来源的输入,而不仅仅是文件。

于 2013-03-13T14:00:06.280 回答
0

很难测试,因为无法换出任务实现。如果没有修改字节码,就没有简单的方法可以查看是否调用了登船。

如果您可以在构造函数或设置器中设置任务实现,则可以传入一个可以监视对启动的调用的实现。

于 2013-03-13T13:45:46.487 回答
0

需要增加字段和类方法的可访问性以进行测试。例如,如果一个人正在测试一种包私有(默认)的方法,那么通常在不同包中的测试用例将无法测试该方法。因此,建议更改字段的可访问性以测试该方法。通过将RescueDamselQuest字段的可访问性从私有修改为默认,可以测试不使用 DI 的DamselRescuingKnight类。然后使用 mockito 编写测试用例。这是测试用例的代码

@Test
public void knightShouldEmbarkOnQuest() throws QuestException {


    DamselRescuingKnight knight = new DamselRescuingKnight();
    RescueDamselQuest quest = mock(RescueDamselQuest.class);
    knight.quest = quest;
    knight.embarkOnQuest();
    verify(quest, times(1)).embark();
}

在 DamselRescuingKnight 类中更改的行以删除私有可访问性

RescueDamselQuest quest;
于 2019-03-28T09:50:51.927 回答