我应该模拟测试对象与之交互的所有对象吗? [英] Should I mock all objects that my test object interacts with?

查看:46
本文介绍了我应该模拟测试对象与之交互的所有对象吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力知道如何决定应该模拟我的测试对象与哪些对象交互.

I am struggling to know how to decide what objects my test object interacts with should be mocked.

class MyClass {
  private Customer customer;
  private Invoice invoice;
  private PrintService ps;
  private DBAccessService da;
  private EmailService em;
  ..........
 }

我可以看到最后 3 个将被模拟,因为它们处理一些外部系统.客户和发票呢?如果没有,为什么?

I can see that the last 3 are to be mocked because they deal with some external systems. What about Customer and Invoice? If not, why?

推荐答案

我应该模拟测试对象与之交互的所有对象吗?"这个问题的一般答案.是一个响亮的:这不是您应该内化或遵循的规则.模拟是多种类型的测试替身之一,您必须判断在哪里使用模拟,在哪里使用其他假或测试替身,以及在哪里使用真正的合作者.我确实同意你的决定,即最后三个字段(服务)可能值得嘲笑,如果由我决定,我会为前两个字段(客户和发票)使用真实对象.

The general answer to the question "Should I mock all objects that my test object interacts with?" is a resounding no: that is not a rule you should internalize or follow. Mocks are one of many types of test double, and you'll have to use judgment about where to use mocks, where to use other fakes or test doubles, and where to use real collaborators. I do agree with your decision that the last three fields (services) are probably worth mocking, and if it were up to me, I would use real objects for the former two fields (Customer and Invoice).

在这里,我将遵循一个准则,不要模拟数据对象,这是根据一些观察得出的:

Here, I would adhere to a guideline, don't mock data objects, which follows from a few observations:

  • 数据对象通常是非常有状态的,而模拟框架往往对状态存根很差.Mockito 对于getX 无限期地返回 15,直到你调用 setX(20),然后 getX 返回 20"来说,Mockito 并没有很好的语法..因此,正确地存根通常很难.

  • Data objects are often extremely stateful, and mocking frameworks tend to stub state poorly. Mockito doesn't really have a great syntax for "getX returns 15 indefinitely, until you call setX(20), then getX returns 20". Thus, stubbing correctly is often hard.

对于只是字段/getter/setter 的数据对象,通过从实际实现中读取可变状态来验证无法完成的价值并没有太大意义.只要读取对象中的值,谁在乎是否调用了 getY ?谁在乎 setY 被调用了多少次,只要正确的值最终出现在对象中?因此,验证通常是不必要的.

For data objects that are just fields/getters/setters, there's not much value to verifying that couldn't be done by reading mutable state out of a real implementation. Who cares whether getY was called, as long as the value in the object was read? Who cares how many times setY was called, as long as the correct value ends up in the object? Thus, verifying is often unnecessary.

数据对象通常在使用它们的对象之前写入,因此通常有一个已经存在的工作实现.

Data objects are usually written before the objects that consume them, so there's often a working implementation that already exists.

数据对象通常具有确定性行为,很少有外部交互,因此在提高测试稳定性或减少测试脆弱性方面通常没有什么好处.

Data objects often have determistic behavior with few external interactions, so there's often little to be gained in improving test stability or reducing test flakiness.

正如问题评论中提到的biziclop

As biziclop mentioned in the question comments,

永远记住自动化测试的目的是什么:以尽可能小的努力在尽可能短的时间内发现错误.或者扭转局面:建立对代码正确性的信心.

always remember what the purpose of automated testing is: to find errors in the shortest possible time with the smallest possible effort. Or to turn it around: to build up confidence about the correctness of your code.

从这个意义上说,模拟数据对象对测试的可读性和正确性有很高的成本,而且不太可能在测试正确性或稳定性方面提供好处.我会避免它.

In this sense, mocking data objects has a high cost to the readability and correctness of your test, and is also unlikely to provide benefit regarding test correctness or stability. I'd avoid it.

这篇关于我应该模拟测试对象与之交互的所有对象吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆