简体   繁体   English

Scala隐式类和函数

[英]Scala implicit classes and functions

I'm trying to refactor some code which uses an implicit class. 我正在尝试重构一些使用隐式类的代码。 Basically, it's code for some unit tests in which I do some mockying and spying with Mockito. 基本上,它是一些单元测试的代码,我在其中使用Mockito进行一些模拟和间谍活动。

In the below example, the mocking of those functions is done in the implicit class A. Each method "overrideX" takes an expected result, overrides the call to method X in myObj and returns myObj (builder pattern for easy chaining multiple overrides later). 在下面的示例中,这些函数的模拟在隐式类A中完成。每个方法“overrideX”获取预期结果,覆盖对myObj中方法X的调用并返回myObj(构建器模式以便以后轻松链接多个覆盖)。

object Outer {
  "call to abc" should {
    "fail if call to X fails" in {
      val failReason = "X failed"
      val myObjMock = B

      myObjMock.overrideX(failReason)
      myObjMock.abc mustEqual failReason
    }

    "fail if call to Y fails" in {
      val failReason = "Y failed"
      val myObjMock = B

      myObjMock.overrideY(failReason)
      myObjMock.abc mustEqual failReason
    }
  }

  implicit class A(myObj: B) {
    def overrideX(result: Result): B = {
      //override call to X in myObj with result
      myObj
    }

    def overrideY(result: Result): B = {
      //override call to Y in myObj with result
      myObj
    }
  }
}    

The problem that I'm trying to solve is to eliminate a lot of boiler plate in the tests. 我试图解决的问题是在测试中消除了大量的锅炉板。 As you can see in the above example, those two tests look very similar. 正如您在上面的示例中看到的那样,这两个测试看起来非常相似。 What I would like to achieve is to create some method common for both which would take the override method and do the actual check. 我想要实现的是创建一些常用的方法,它们将采用覆盖方法并进行实际检查。

def somethingElse(result: Result, f: Result => B) = {
    val myObjMock = B
    myObjMock.f(result).abc mustEqual result
}

The tests would look something like 测试看起来像

"call to abc" should {
    "fail if call to X fails" in {
      val failReason = "X failed"
      somethingElse(failReason, overrideX)
    }

    "fail if call to Y fails" in {
      val failReason = "Y failed"
      somethingElse(failReason, overrideY)
    }
  }

I know that the overrideX and overrideY methods are on the class and not on a companion object. 我知道overrideX和overrideY方法在类上,而不在伴随对象上。

I currently have a version in which the overrideXX methods are in a companion object and take the result and the validator as parameters. 我目前有一个版本,其中overrideXX方法在伴随对象中,并将结果和验证器作为参数。 But they are not implicit and I had to drop the builder pattern, so no chaining on them. 但它们并不是隐含的,我不得不放弃构建器模式,因此不会对它们进行链接。

I think what you need is a function (B, Result) => B instead of Result => B . 我认为你需要的是一个函数(B, Result) => B而不是Result => B If you have a variable f that contains a function you cannot call it on an object like myObjMock.f(...) . 如果你有一个包含函数的变量f ,你不能在像myObjMock.f(...)这样的对象上调用它。 But you can pass myObjMock into f , like f(myObjMock, ...) . 但你可以将myObjMock传递给f ,就像f(myObjMock, ...)

def somethingElse(result: Result, f: (B, Result) => B) = {
  val myObjMock = B
  f(myObjMock, result).abc mustEqual result
}

"call to abc" should {
  "fail if call to X fails" in {
    val failReason = "X failed"
    somethingElse(failReason, _.overrideX(_))
  }

  "fail if call to Y fails" in {
    val failReason = "Y failed"
    somethingElse(failReason, _.overrideY(_))
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM