ScalaMock. Mock a class that takes arguments

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

Full disclosure: I'm very new to mocking and mocking frameworks. I'm trying to use ScalaMock because it seemed like the 'default' mocking framework to use with ScalaTest but I am happy to use any other framework which is compatible with ScalaTest.

The problem: I've written in Scala a class that talks to a socket. The class has a type parameter of what sort of socket it is to talk to and one of it's arguments is a factory for creating sockets of that type. It has the signature:

class XScanner[T <: SocketClient](   confPath: String = "/etc/default/configPath",   socketClientFactory: String => T ) extends ScannerBase(path) 

I would like to be able to write unit tests for this class by supplying a mock SocketClient so my test code doesn't have to connect to a real socket but I can't work out how to do this with ScalaMock.

My test code looks like this:

val t = new XScanner[SocketClient](confPath, (s: String) => mock[SocketClient]) 

Clearly that won't compile because SocketClient expects a path to the socket as an argument but I can't call mock[SocketClient(s)] because that's not a type and I can't call mock[SocketClient](s) because mock doesn't take the arguments of the type passed to it as it's own arguments.

So how can I write a mock SocketClient factory to pass to my Scanner? I can't even work out how to mock a class that takes arguments!

回答1:

The insight is that what you need to mock is socketClientFactory. And then set it up to return a mock SocketClient.

Given:

trait SocketClient {   def frobnicate(): Unit }  class ScannerBase(path: String)  class XScanner[T <: SocketClient](   confPath: String = "/etc/default/configPath",   socketClientFactory: String => T ) extends ScannerBase(confPath) {   val socket = socketClientFactory("Some Socket Name")   socket.frobnicate } 

(side note - your default value for confPath can never be used because there's no default value for socketClientFactory).

then this should get you started (this is with Scala 2.9.x and ScalaMock2 - 2.10.x with ScalaMock3 will be slightly different, but not much so):

import org.scalatest.FunSuite import org.scalamock.scalatest.MockFactory import org.scalamock.generated.GeneratedMockFactory  class ScannerTest extends FunSuite with MockFactory with GeneratedMockFactory {    test("scanner") {     val mockFactory = mockFunction[String, SocketClient]     val mockClient = mock[SocketClient]     mockFactory.expects("Some Socket Name").returning(mockClient)     mockClient.expects.frobnicate     val scanner = new XScanner("path/to/config", mockFactory)   } } 

For completeness, here's the same test in Scala 2.10.0 and ScalaMock3:

import org.scalatest.FunSuite import org.scalamock.scalatest.MockFactory  class ScannerTest extends FunSuite with MockFactory {    test("scanner") {     val mockFactory = mockFunction[String, SocketClient]     val mockClient = mock[SocketClient]     mockFactory.expects("Some Socket Name").returning(mockClient)     (mockClient.frobnicate _).expects()     val scanner = new XScanner("path/to/config", mockFactory)   } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!