仅进行模拟验证的单元测试是否有问题?

6 投票
3 回答
569 浏览
提问于 2025-04-16 09:52

我有一个类,它连接了另外三个服务,这个设计是为了让实现这些服务变得更加灵活。不过,我的大部分单元测试逻辑都是在验证模拟对象。有没有办法重新设计一下,避免这种情况呢?

这里有个Python的例子:

class Input(object): pass

class Output(object): pass

class Finder(object): pass

class Correlator(object): pass
  def __init__(self, input, output, finder):
    pass
  def run():
    finder.find(input.GetRows())
    output.print(finder)

我还得模拟输入、输出和查找功能。即使我再做一个抽象,把一些东西从Correlator.run()返回,还是得把它当作模拟对象来测试。

3 个回答

0

乍一看,这里的问题似乎是模拟的程度太高了。如果你在使用动态语言(我假设你在用Python),我建议你可以尝试创建一些生产类的子类,重写那些最麻烦的方法,并提供模拟的数据,这样你就能得到生产代码和模拟代码的结合。如果你的代码路径不允许实例化这些对象,我建议你可以尝试猴子补丁,用替代的方法返回模拟数据。

是否存在代码异味还取决于模拟数据的质量。根据我的经验,使用调试工具,复制粘贴已知正确的数据,或者从网络中抓取数据,都是确保数据质量的好方法。

集成测试和单元测试之间的选择也是一个经济问题:用集成测试或功能测试替代单元测试有多麻烦?系统规模越大,使用轻量级模拟的好处就越明显,因此单元测试的价值也越高。

2

其实没必要只用单元测试——在这种情况下,集成测试可能更有用。你可以把所有的对象都初始化好,稍微用一下主类,然后检查一下结果(可能会比较复杂)。这样你就能测试接口、输出的可预测性,以及其他在更高层次上很重要的东西。我之前也用过这种方法,发现那些很难进行集成测试的东西,往往属性或者参数太多,或者输出格式太复杂/错误。

2

你可以问问自己:在这个特定的测试案例中,你到底需要检查什么?如果这个检查不依赖于其他类不是虚假的,那么就没问题。

不过,通常使用很多虚拟对象(mock)可能意味着你在尝试测试集成,但实际上并没有真正进行集成测试。所以如果你认为一个类在用虚拟对象测试通过了,就可以在真实类中正常工作,那你可能需要再写一些测试。

就我个人而言,我几乎不写单元测试。我是个网页开发者,更喜欢功能测试,通过HTTP请求来测试整个应用,就像用户使用一样。不过你的情况可能会有所不同。

撰写回答