2013-05-31 87 views
7

我正在使用scalamock來模擬一個包含一些重載方法的類,但我收到了一些錯誤。嘲笑重載方法

例如:

val out = mock[PrintStream] 

(out.print _).expects("cmd \r\n") 

引發以下錯誤:

[error] [...]/src/test/scala/chili.scala:19: ambiguous reference to overloaded definition, 
[error] both method print in class PrintStream of type (x$1: String)Unit 
[error] and method print in class PrintStream of type (x$1: Array[Char])Unit 

但是,如果我嘗試使用:

(out.print(_: String)).expects("cmd \r\n") 

我也得到一個錯誤:

[info] [...]/src/test/scala/chili.scala:19: Unable to resolve overloaded method print 
[info]  (out.print(_: String)).expects("cmd \r\n") 
[info]    ^
[error] [...]/src/test/scala/chili.scala:19: value expects is not a member of String => Unit 
[error]  (out.print(_: String)).expects("cmd \r\n") 

有什麼辦法可以在scala中做到這一點?也許使用另一個庫?

回答

10

我相信你所看到的編譯器錯誤與scalamock無法正確地模擬PrintStream類有關。如果看scalamock scaladocs你會看到聲明:

At present, ScalaMock can only mock traits, Java interfaces, and non-final 
classes that define a default constructor 

由於PrintStream類既不是一個接口也不會有默認的構造函數,我的猜測是,scalamock不能正確地嘲笑它,你所看到的錯誤這是一個副作用。如果你改變了你的代碼使用OutputStream,而不是(這是一個接口,從而滿足scalamock的限制),你可以做你的重載方法嘲諷這樣的:

val mockStream = mock[OutputStream]  
(mockStream.write(_:Int)) expects(1) 
(mockStream.write(_:Array[Byte])) expects(Array[Byte](1,2,3)) 

就個人而言,我更喜歡的Mockito內Specs2使用它沒有這些限制。使用PrintWriter和一類的一個實例,然後使用具有的Mockito嘲笑那類測試規範如下:

import java.io.PrintStream 
import java.io.File 
import org.specs2.mutable.Specification 
import org.specs2.mock.Mockito 

class MockitoExample extends Specification with Mockito{ 
    val mockPrinter = mock[PrintStream] 
    val myPrinter = new MyPrintingClass{ 
    override val printer = mockPrinter 
    } 

    "A request to print and attay of strings" should{ 
    "call println on the PrintStream for each string supplied" in { 
     myPrinter print Array("foo", "bar") 
     there was one(mockPrinter).println("foo") 
     there was one(mockPrinter).println("bar") 
    } 
    } 
} 

class MyPrintingClass{ 
    val printer = new PrintStream(new File("foo.txt")) 

    def print(strings:Array[String]) = strings foreach (printer.println(_)) 
} 

現在,這是一個很簡單的例子,只使用測試後驗證沒有預先測試stubbings (因爲println的返回類型爲Unit),但至少可以看出Mockito不會受到與scalamock相同的限制。你可以閱讀更多關於使用Mockito Specs2 here

+0

很好的答案。謝謝 – simao