如何编写Scala单元测试以验证是否使用某个特定函数作为参数调用函数?

时间:2015-05-29 17:33:56

标签: function scala unit-testing verify

我有一个班级:

class SomeDao {
  this: support =>

  def get(id:Long): Option[SomeDto] = {
     support.sprocCall(SomeDto.fromResultSet, SomeDao.getSproc, id)
  }  
}

SomeDto.fromResultSet实际上是一个Function1 [WrapperResultSet,SomeDto]。

是否可以验证是否已使用正确的函数作为第一个参数调用support.sprocCall?

2 个答案:

答案 0 :(得分:1)

这个问题有两个部分。首先,您需要测试类中方法调用的参数是什么。其次,你想要做某种形式的功能平等。

如评论中所述,要解决第一个问题,您可以使用Mockito。请参阅下面的示例,了解如何使用ArgumentCaptor

现在,第二部分更复杂。请参阅有关功能平等的答案here。在下面的代码示例中,我强制将函数func1func2实例化,并将它们分别存储到val func_aval func_b中。然后我在整个测试代码中使用了两个val。如果在测试过程中无法做类似的事情,那么恐怕没有什么好方法可以达到你所需要的。

为了更好地显示Scala中函数相等的问题,我在示例中添加了最后两行。

import org.mockito.ArgumentCaptor
import org.mockito.Matchers._
import org.mockito.Mockito._

object ToyExample extends App {
  // A toy class
  class TargetClass {
    def add(str: String, func: String => Long, j: Long): Long = func(str) + j
  }

  // These are the two functions we can use 
  def func1(g: String): Long = g.toLong
  def func2(g: String): Long = g.toLong * 2

  // Here is an example of using the TargetClass 
  val actualInstance = new TargetClass
  println( actualInstance.add("12", ToyExample.func1, 2) ) // Prints 14

  // Here is with the mock
  val mockedSomeDao = mock(classOf[TargetClass])

  val func_a = func1 _
  val func_b = func2 _

  // ... use the mocked object to do what you want
  mockedSomeDao.add("12", func_a,  2)

  // Now verify that the argument is the right one
  val argument = ArgumentCaptor.forClass(classOf[(String) => Long])

  verify(mockedSomeDao, atLeastOnce()).add(anyString(), argument.capture(), anyLong())

  if( argument.getValue eq func_a ) {
    println("Func 1") // This one gets called
  } else if (argument.getValue eq func_b) {
    println("Func 2")
  }

  println( func_a eq func_a) // Prints "true"
  println( func1 _ eq func1 _) // Prints "false"!
}

答案 1 :(得分:0)

你正在非常接近确定两个函数是否相等的问题。 SO上已多次涉及该特定问题,例如How to compare Scala function values for equality 我相信你的问题只是这个问题的一般形式。如果是这样,那么答案就是你无法在理论上建立起来。