扩展特征的单元测试类 - 我如何在特征中模拟和存根方法?

Posted

技术标签:

【中文标题】扩展特征的单元测试类 - 我如何在特征中模拟和存根方法?【英文标题】:Unit testing class that extends a trait - how do I mock and stub methods in the trait? 【发布时间】:2015-11-14 18:41:36 【问题描述】:

我正在使用 scalatest 对扩展 trait 的类进行单元测试(从某种意义上说,我的类正在使用 trait 作为 mixin)。

特征包含的方法是辅助方法(最终调用数据库中的一些查找),我想将其存根,以便我可以隔离我的类的功能。但是我还没有找到像 Mockito 或 ScalaMock 这样的框架来实现这一点。

问题:可以使用模拟框架来实现吗?如果可以,如何实现?如果没有,我很想知道是否有原因。

例如。

trait MyTrait 
  def usefulMethod(i: int) = ...



class MyClass extends MyTrait 
  def numberCruncher = 
     val x = usefulMethod(1) + 1
  

我需要根据 i 的值返回不同的存根答案。类似于 Mockito 的 when(myTrait.usefulMethod(1)).thenReturn(10)

我还需要验证是否在具有正确值的 trait 中调用了不同的方法。

本质上,我是在再次询问this question,但我注意到这是在 2011 年提出的,事情很可能已经发生了变化。可能会有新的框架和新的方法。这个 2001 年的问题也没有询问如何验证特征中的方法。

问题:以这种方式使用 traits-as-a-mixin 是否真的会阻止使用模拟框架对 mixin 中的方法进行模拟/存根进行单元测试的能力?即,模拟和存根框架是否依赖于依赖注入的使用?

PS。直到现在我一直在使用 Mockito,但我并不反对使用 scalamock 或任何其他框架。我研究了 scalamock,因为它宣传它可以测试特征,但是从 scalamock 自己的测试看来,虽然它可以模拟特征,但如果该特征作为依赖项传递给类而不是类,则只能存根模拟行为扩展该特征。见here

【问题讨论】:

Unit testing helper or non-interface traits in Scala的可能重复 【参考方案1】:

我通常将被测类子类化以替换我想模拟的方法:

var usefulInput: Option[Int] = Nont
val testInstance = new MyClass 
  override def usefulMethod(i: Int) = 
    usefulInput = Some(i)
    42
  


testInstance.numberCruncher should equal(43)
usefulInput should equal(Some(1))

我发现内联覆盖通常比任何模拟框架更易于实现和阅读

【讨论】:

但是你这样做是因为它不可能以任何其他方式吗?这确实是我的问题。 嗨,Arne,我也意识到这个方法可以用来消除响应,但是如果你还需要验证一个特征上的方法是用正确的值调用的呢?就像使用模拟框架一样。 就我个人而言,我发现这种形式的嘲讽在你几周后回来时更容易理解,因为它是如此明确。所以我什至没有费心尝试用 scala 模拟框架。至于验证,您可以使用计数器,或将 args 填充到列表中进行检查。我做了两种变体 抱歉,您无法回答我的实际问题,即是否可能在现有框架中做我想做的事情(2015 年)。

以上是关于扩展特征的单元测试类 - 我如何在特征中模拟和存根方法?的主要内容,如果未能解决你的问题,请参考以下文章

模拟测试特征和模拟方法

Scala - 为使用数据库连接扩展特征/类的对象/单例编写单元测试

如何对 PHP 特征进行单元测试

单元测试术语的概述(存根与模拟,集成与交互)?

如何在 Flutter 集成测试中最好地存根/模拟 rest API 调用

单元测试如何使用 Mockito 模拟存储库