2016-12-12 113 views
3

我想重构一些使用隐式类的代码。 基本上,它是一些单元测试的代码,我在其中使用Mockito进行一些模拟和间谍活动。斯卡拉隐式类和函数

在下面的实例中,这些功能的嘲笑在隐式类A.每个方法“overrideX”需要一个预期的结果完成后,将覆盖在调用方法中的X MyObj中并返回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 
    } 
    } 
}  

我试图解决的问题是在测试中消除了大量的锅炉板。正如你在上面的例子中看到的那样,这两个测试看起来非常相似。 我想实现的是创建一些通用的方法,这两种方法都采用覆盖方法并进行实际检查。

def somethingElse(result: Result, f: Result => B) = { 
    val myObjMock = B 
    myObjMock.f(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) 
    } 
    } 

我知道overrideX和overrideY方法是在类,而不是一个同伴对象。

我目前有一个版本,其中的overrideXX方法在伴随对象中,并将结果和验证器作为参数。但他们不是隐含的,我不得不放弃建设者的模式,所以不要束缚他们。

回答

2

我觉得你需要的是一个函数(B, Result) => B而不是Result => B。如果变量f包含一个函数,则不能在像myObjMock.f(...)这样的对象上调用它。但你可以通过myObjMockf,如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(_)) 
    } 
} 
+0

非常感谢。奇迹般有效。直到现在还不知道_.methodCall(_)的东西。 –