【问题标题】:ScalaMock - Mocking higher order functionsScalaMock - 模拟高阶函数
【发布时间】:2018-06-15 19:28:58
【问题描述】:

我需要一些帮助,了解如何使用 ScalaMock 在类中模拟高阶函数

import org.scalamock.scalatest.MockFactory
import org.scalatest.{FlatSpec, Matchers}

class TestSpec extends FlatSpec with MockFactory with Matchers {

  class Foo {
    def foo(f: () ⇒ String) = "this is foo"
  }

  val fooMock = mock[Foo]

  "Failing test" should "pass but doesn't" in {
    (fooMock
      .foo(_: () ⇒ String))
      .expects({ () ⇒
        "bar"
      })
      .returns("this is the test")

    // will fail here
    val result = fooMock.foo({ () ⇒
      "bar"
    })

    assert(true)
  }

  "Passing test" should "that passes but I can't do it this way" in {
    val f = { () ⇒
      "bar"
    }

    (fooMock.foo(_: () ⇒ String)).expects(f).returns("this is the test")

    val result = fooMock.foo(f)

    result shouldBe "this is the test"
  }
}

正如您在上面的代码中看到的那样,当您传入一个具有更高阶函数的值时,被模拟的函数可以正常工作,但如果您在每个位置都输入它,则不会。在我的用例中,我不能像在第二次测试中那样做

以下是有关用例的更多信息,但并非完全需要回答这个问题

这是一个简化的示例,但我需要一种方法来让前者工作。原因是(我会尽力解释这一点)我有一个正在测试的 A 类。 A 内部是一个传递模拟类 B 的函数,基本上 foo 函数(如下所示)在这个模拟 B 内部,我不能像在下面的第二个示例中那样只传递 f。如果这没有任何意义,我可以尝试准确地复制它。

TL;DR 我需要第一次测试才能工作,哈哈

任何想法为什么会发生这种情况?

如果您对我为什么需要这样做感到好奇,这里有一个更准确的示例,说明我是如何使用它的:

import org.scalamock.scalatest.MockFactory
import org.scalatest.{FlatSpec, Matchers}

class TestSpec extends FlatSpec with MockFactory with Matchers {

  class Foo {
    def foo(f: () ⇒ String) = s"you sent in: ${f()}"
  }

  object Bar {

    def bar(foo: Foo): String = {
      val f = { () ⇒ "bar" }

      foo.foo(f)
    }
  }

  val fooMock = mock[Foo]

  "Failing test" should "pass but doesn't" in {
    (fooMock.foo(_: () ⇒ String))
      .expects({ () ⇒
        "bar"
      })
      .returns("this is the test")

    // will fail here
    val result = Bar.bar(fooMock)

    assert(true)
  }
}

【问题讨论】:

    标签: scala unit-testing mocking higher-order-functions scalamock


    【解决方案1】:

    这不起作用的原因归结为 Scala 本身。 例如看到这个scala repl:

    scala> val f = { () ⇒ "bar" }
    f: () => String = $$Lambda$1031/294651011@14a049f9
    
    scala> val g = { () ⇒ "bar" }
    g: () => String = $$Lambda$1040/1907228381@9301672
    
    scala> g == f
    res0: Boolean = false
    

    所以 ScalaMock 在没有帮助的情况下也无法比较函数是否相等。 我的建议是,如果您只对函数的结果感兴趣,请使用谓词匹配,如此处文档中所述:http://scalamock.org/user-guide/matching/

    在谓词中,您可以评估捕获的参数并检查返回值是否确实是bar。或者,如果你的函数更复杂,也许你甚至可以做一个mock[() => String] 并在匹配器中比较引用相等性?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      • 2016-05-07
      相关资源
      最近更新 更多