Wie zum Hohn eine Scala singleton-Objekt?
Ich versuche, mich zu verspotten, ein Scala singleton-Objekt. Insbesondere brauche ich zum simulieren der Objekt play.api.libs.ws.WS
im service-Komponente (class under test).
Mit Mockito ist dies nicht möglich, die test-Durchführung scheitert in der folgenden Weise:
[error] MockitoException: :
[error] Cannot mock/spy class play.api.libs.ws.WS$
[error] Mockito cannot mock/spy following:
[error] - final classes
[error] - anonymous classes
[error] - primitive types (GeolocationSpec.scala:18)
Lesen hier, es scheint, dass Scalamock erlaubt, es zu tun:
Zu verspotten standalone-singleton-Objekt, verwenden
org.scalamock.annotation.mockObject
.
Mein service-Komponente ist so etwas wie dieses:
trait GeolocationService {
def wsClient = WS
def getPath(origin: Location, destination: Location): Future[Route]
}
class DefaultGeolocationService extends GeolocationService {
val serviceProviderEndpoint = Play.current.configuration.getString("api.directions.endpoint")
override def getPath(origin: Location, destination: Location): Future[Route] = {
val params = Seq(
"origin" -> s"${origin.lat},${origin.lon}",
"destination" -> s"${destination.lat},${destination.lon}"
);
val resp = wsClient.url(serviceProviderEndpoint.get).withQueryString(params: _*).get()
resp.map {
//omitted code
}
}
}
Meine bauen.sbt hat alle diese Abhängigkeiten:
[...]
"org.scalatest" %% "scalatest" % "2.2.1",
"org.specs2" %% "specs2" % "2.3.13" % "test",
"org.scalamock" %% "scalamock-specs2-support" % "3.0.1" % "test",
"org.scalamock" %% "scalamock-scalatest-support" % "3.0.1" % "test",
"org.scalamock" %% "scalamock" % "3.0.1",
[...]
aber ich kann nicht finden dieser: org.scalamock.annotation.mockObject
Wahrscheinlich diese kann getan werden, auch mit EasyMock und PowerMock, aber ich finde keine Scala-Beispiel-code.
Irgendeine Idee?
- Mock das interface implementiert, statt. Nehmen Sie das interface als eine Abhängigkeit, wo es verwendet wird.
- Wie nennst du es? Wie
mock [WS.type]
oder anderen Weg? - Ich schließe mich @PolymorphicPotato. Es ist bedauerlich, dass Spielen WS ist ein Objekt statt einer Implementierung ein generisches Merkmal. Wenn Sie können auch ein kurzes snippet des Codes durch die Verwendung von WS können wir führen Sie zu entkoppeln es von der WS und es einfacher machen, zu verspotten.
- ja, der einzige Weg fand ich mit Mockito zu verspotten, ein Objekt, ohne es zu kompilieren Fehler ist
mock[WS.type]
, aber es funktioniert nicht. - Können Sie mir sagen, was genau du meinst? Die Schnittstelle würde Sie verspotten im Falle von WS singleton-Objekt?
- Den code Hinzugefügt, der mit WS.
- Ich habe nicht Ihre Frage zu verstehen. Wollen Sie mock-webservice-Aufruf des Codes in Ihre tests?
- Ja, ich möchte mock-Objekt
wsClient
innenGeolocationService
Rückgabe eines mockWSRequestHolder
Klasse, wenn dieurl(url: String)
- Methode aufgerufen wird. Das problem ist, dass wsClient ist ein singleton-Objekt, das kann ich nicht umgestalten, Sie wird bereitgestellt von Play framework.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Spott singleton-Objekte mit ScalaMock 3 ist nicht möglich, doch Paul Metzger erwartet wieder einzuführen, dieses feature in ScalaMock 4 (siehe http://paulbutcher.com/2014/04/15/scalamock-status-report/)
Don ' T mock the singleton. Statt WS, machen Sie Ihre service-Komponenten sind auf eine dünne Fassade verstecken:
und in Ihren test, nur überschreiben ws-Methode mit einem Modell, das jetzt einfach zu erstellen:
Ich weiß nicht, wie Sie das design ändern, um Platz für diese Art von Einschränkung. im Grunde genommen, was ich kriegen kann alles ändern das design, und verwenden Sie dann die mock-framework -
hoffe, es hilft.
Warum Sie nicht die Kuchen-Muster?
Es ist ein bisschen verbose, aber es löst Ihre spöttischen problem.
Können Sie auch verwenden, Monaden, dies zu tun, aber ich habe nie realisiert, es ist hier beschrieben:
Scala dependency injection: alternativen zur impliziten Parameter