Mockito与ScalaTest的结合使用

在.NET环境中,有许多模拟(mocking)工具可以选择,例如Moq、FakeItEasy和RhinoMocks等。个人更熟悉Moq,因此在寻找JVM平台的模拟框架时,希望找到一个语法与.NET中相似的工具。在JVM平台上,有几个不错的选择,如ScalaMock、EasyMock、JMock和Mockito,它们都可以很好地与ScalaTest配合使用。在这些选项中,最终选择了Mockito,因为它的语法最符合喜好,并且它的文档齐全,Google搜索结果也很正面。

SBT依赖要求

与之前的大多数文章一样,需要使用SBT来获取库。因此,SBT文件需要包含以下内容:

libraryDependencies ++= Seq( "org.mockito" % "mockito-core" % "1.8.5", "org.scalatest" %% "scalatest" % "2.2.5" % "test" )

第一个示例

让来看一个简单的例子。这个例子模拟了一个java.util.ArrayList[String],并设置了一些验证

class FlatSpec_Mocking_Tests extends FlatSpec with Matchers with MockitoSugar { "Testing using Mockito" should "be easy" in { // mock creation val mockedList = mock[java.util.ArrayList[String]] // using mock object mockedList.add("one") mockedList.clear() // verification verify(mockedList).add("one") verify(mockedList).clear() } }

可能会注意到,如何能够模拟ArrayList[T]的,尽管它不是一个抽象类。这是非常酷的。

桩(Stubbing)

使用Mockito,也可以像预期的那样桩出东西。这里有一个例子,尝试模拟一个简单的特质(trait)。

trait DumbFormatter { def formatWithDataTimePrefix(inputString: String, date: Date): String = { s"date : $date : $inputString" } def getDate(): String = { new Date().toString } } class FlatSpec_Mocking_Tests extends FlatSpec with Matchers with MockitoSugar { "Stubbing using Mockito" should "be easy" in { var mockDumbFormatter = mock[DumbFormatter] when(mockDumbFormatter.getDate()).thenReturn("01/01/2015") assert("01/01/2015" === mockDumbFormatter.getDate()) } }

在上面的例子中,可以看到模拟一个特质是多么容易。也可以看到如何使用Mockito函数when和thenReturn来桩出模拟的。

返回值

刚刚看到了如何使用Mockito函数thenReturn来设置返回值。如果想设置一个动态返回值,这可以很容易地调用一些其他函数来创建返回值。

参数匹配

Mockito提供了一些功能,允许匹配任何参数值。它还提供了正则表达式匹配器,并允许编写自定义匹配器,如果内置的匹配器不满足需求。

class FlatSpec_Mocking_Tests extends FlatSpec with Matchers with MockitoSugar { "Stubbing using Mockito" should "be easy" in { var mockDumbFormatter = mock[DumbFormatter] when(mockDumbFormatter.formatWithDataTimePrefix(anyString(), any[Date]())).thenReturn("01/01/2015 Something") assert("01/01/2015 Something" === mockDumbFormatter.formatWithDataTimePrefix("blah blah blah", new Date())) } }

在上面的例子中,使用了标准的参数匹配器。

异常

要使用Mockito抛出异常,只需要使用thenThrow(…)函数。

class FlatSpec_Mocking_Tests extends FlatSpec with Matchers with MockitoSugar { "Stubbing using Mockito" should "be easy" in { var mockDumbFormatter = mock[DumbFormatter] when(mockDumbFormatter.formatWithDataTimePrefix(anyString(), any[Date]())).thenThrow(new RuntimeException()) intercept[RuntimeException] { mockDumbFormatter.formatWithDataTimePrefix("blah blah blah", new Date()) } } }

如所见,还需要使用ScalaTest的intercept来实际测试。

回调(CallBacks)

回调在想看到方法被调用了什么,然后可以做出明智的决定可能返回什么时很有用。

class FlatSpec_Mocking_Tests extends FlatSpec with Matchers with MockitoSugar { "Stubbing using Mockito" should "be easy" in { var mockDumbFormatter = mock[DumbFormatter] when(mockDumbFormatter.formatWithDataTimePrefix(anyString(), any[Date]())).thenAnswer(new Answer[String] { override def answer(invocation: InvocationOnMock): String = { val result = "called back nicely sir" println(result) result } }) assert("called back nicely sir" === mockDumbFormatter.formatWithDataTimePrefix("blah blah blah", new Date())) } }

在上面的例子中,使用了Mockito的thenAnswer函数,以及如何使用匿名Answer对象。

验证

最后,想谈谈验证。这可能包括验证函数是否被调用,以及是否被调用了正确次数。

class FlatSpec_Mocking_Tests extends FlatSpec with Matchers with MockitoSugar { "Stubbing using Mockito" should "be easy" in { var mockDumbFormatter = mock[DumbFormatter] when(mockDumbFormatter.formatWithDataTimePrefix(anyString(), any[Date]())).thenReturn("someString") val theDate = new Date() val theResult = mockDumbFormatter.formatWithDataTimePrefix("blah blah blah", theDate) val theResult2 = mockDumbFormatter.formatWithDataTimePrefix("no no no", theDate) verify(mockDumbFormatter, atLeastOnce()).formatWithDataTimePrefix("blah blah blah", theDate) verify(mockDumbFormatter, times(1)).formatWithDataTimePrefix("no no no", theDate) } }

在上面的例子中,验证了函数是否被调用,以及是否被调用了正确次数。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485