【问题标题】:Can Mockito detect mock usage and field assignments?Mockito 可以检测模拟使用和字段分配吗?
【发布时间】:2017-06-26 04:09:58
【问题描述】:

这个用例也许最好通过测试来解释:

@Test
public void testZeroInteraction() {
    Pika pika = new Pika();
    Trainer trainer=mock(Trainer.class);

    pika.doNothing3(trainer);
    verifyZeroInteractions(trainer);
}

这是我在Pika 类中的doNothing3() 方法:

void doNothing3(Trainer trainerIn){
    trainer=trainerIn;
    trainerIn.name="Ash";
}

在这种情况下,verifyZeroInteractions() 不会抱怨并且测试通过了。

Mockito 可以像上面的 doNothing3 方法中那样检测分配吗?

如果可以,可以使用什么 Mockito 方法?

【问题讨论】:

    标签: unit-testing mocking mockito


    【解决方案1】:

    OO 是关于行为,而不是状态

    Mockito documentation 的第一段内容如下:

    让我们验证一些行为! ...

    从这个意义上说;当 Mockito 谈到 交互 时,它们(或据我所知的任何其他模拟框架)的意思是:方法调用。

    换句话说:mocked 对象对它所模拟的类的字段一无所知

    所以,你基本上可以做到以下几点:

    1. 保留当前的testZeroInteraction() 测试(以证明没有调用任何方法
    2. 添加第二个测试,以检查真实输入对象是否没有变化

    喜欢:

    @Test
    public void testFieldUpdates() {
      Pika pika = new Pika();
      Trainer orig = new Trainer();  
      Trainer copy = new Trainer(orig);
      pika.doNothing3(copy);
      assertThat(orig, is(copy));
    

    }

    这个测试“意味着”什么:创建一个训练器对象,然后创建它的副本。将第一个对象传递给您的方法;然后检查该对象是否仍然是equals 副本。

    但是当然——这需要你有某种“拷贝构造函数”;也是equals()的合理实现。

    最后:您实际上应该从退后一步开始。我的第一句话是:“OO 是关于行为,而不是状态”。翻译为:让 Trainer 类具有 public writeable 字段的想法是一种设计气味。你不应该那样做。您无需创建对象、传递它们并让其他代码直接写入字段。您在其他对象上调用方法,而不是操纵它们的状态。

    换句话说:您的方法违反了一整套重要的面向对象原则。正因为如此,Mockito 不支持你正在做的事情。因为没有人应该做你正在做的事情。因此,如前所述:真正的 答案是修复您损坏的设计。

    【讨论】:

    • GhostCat,感谢您的详细回答。我同意 - 字段的公共可访问性是一个问题,应该注意使用 getter 和 setter。但是 - 我想这与 Mockito 内部有关 - Mockito 可以很容易地实现对字段的支持,对吧?毕竟,字段和函数都作为成员绑定到对象。
    • 老实说:我不能说。你看,当你编写一个模拟对象时,你仍然有 method 调用进来。你有一些 active 触发器。而字段更新就像“被动”。本质上,它只是对某个内存位置的写入。该路径中没有“没有”会触发您写入的对象上的某些内容。如果这是可能的,我会感到非常惊讶;即使是肮脏的黑客式的事情。
    • 有趣。所以,同样的道理,也很难知道trainer=trainerIn;这行是否被执行了,因为它只是在读取trainerIn的内存地址。
    • 唯一的检查方法是:trainer 显然是其他类的一个字段。然后,您必须检查该 other 类的 state
    • 重点是状态。当然你需要 internal 状态来实现行为。但是:理想情况下,类的外部接口应该提供行为而不是状态。例如,您可能想了解“告诉不问”的原则。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多