【问题标题】:Should I Mock the Trait or Mock the Class Using Scala Mock我应该使用 Scala Mock 来模拟特征还是模拟类
【发布时间】:2021-01-25 18:28:06
【问题描述】:

假设我有以下内容:

@ImplementedBy(classOf[DefaultFoo])
trait Foo {
  def a (s : String) : Int
}

class DefaultFoo @Inject()() extends Foo{

  override def a (s : String) = 1

}

@ImplementedBy(classOf[DefaultBaz])
trait Baz {
  def b (s : String) : Int
}

class DefaultBaz @Inject()(val f :Foo) extends Baz{

  override def a (s : String) = 1

}

如果我想测试,比如 DefaultBaz,我通常使用 ScalaMock,我会在我的测试规范中模拟如下:

class DefaultBazSpec extends AnyWordSpec with MockFactory{

   val mockFoo = mock[Foo]
val b = new DefaultBaz(mockFoo)

   // write tests
}

但我也可以这样做:

val mockFoo = mock[DefaultFoo]

哪个更好?模拟 trait 还是默认的类实现?

【问题讨论】:

  • 为什么不只是用一个简单的类来扩展特征,它可以做模拟会做的事情,但没有反射和花哨的语法。
  • 我没有举一个很好的例子。我想描述一个将Foo 注入另一个类的场景。该类的测试将使用使用 Scalamock 的 Foo 的模拟版本。现在我可以做 mock[Foo]mock[DefaultFoo] 。我想知道这样做的利弊
  • 我认为您的 sn-p 中有一些错误,您可能希望 DefaultBaz 扩展 Baz 并接收 Foo 的实例作为参数。 - 无论如何,我知道您习惯于使用反射来解决 (complicate) 每一个琐碎的问题,例如传递依赖项和测试。但是,Scala 中的许多人更喜欢保持简单,只手动传递依赖项并使用简单的存根进行测试而不是模拟。
  • 是的,抱歉,我修复了这个问题,并表明我正在使用 Guice DI 框架。我知道 FP 方法说不要使用 DI,但我使用的是 Play Framework,它带有 Guice DI,所以我正在使用它,这就是我以这种方式进行测试的原因,
  • 主要是因为您的DefaultBaz 应该适用于任何Foo,还因为模拟DefaultFoo 可能比普通界面更难(顺便说一句,不需要模拟,但你一定厌倦了我一遍又一遍地重复).

标签: scala scalamock


【解决方案1】:

最好都不用。通常应避免模拟(尤其是在 Scala 中)。

但即使您决定继续使用模拟,模拟被测类也会破坏测试的全部目的:被测代码与生产代码没有任何共同之处。

Mocks 用于模拟被测类的依赖项(例如构造函数参数或方法参数)。

【讨论】:

  • 我使用mocks的方式是模拟上例中类中方法的行为。比如说,我有另一个类注入了Foo。然后在我对这个其他类的测试中,我将只做val f = mock[Foo],然后为方法a 的行为编写模拟,这样它们就可以用来测试这个其他类。请参阅我更新的帖子。它更好地描述了场景
  • 然后嘲笑Foo 是一个较小的邪恶
  • 嘲笑 DefaultFoo 有什么坏处——这是我的主要问题@simajdo
猜你喜欢
  • 1970-01-01
  • 2019-02-13
  • 2012-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-11
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多