2013-01-11 11 views
5

Divulgazione completa: sono molto nuovo per le strutture di derisione e derisione. Sto cercando di usare ScalaMock perché mi sembrava il framework di simulazione "predefinito" da utilizzare con ScalaTest, ma sono felice di utilizzare qualsiasi altro framework che sia compatibile con ScalaTest.ScalaMock. Mock una classe che prende argomenti

Il problema: ho scritto in Scala una classe che parla con un socket. La classe ha un parametro di tipo sul tipo di socket con cui parlare e uno degli argomenti è una factory per la creazione di socket di quel tipo. Ha la firma:

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

mi piacerebbe essere in grado di scrivere unit test per questa classe, fornendo un SocketClient finto quindi il mio codice di prova non deve collegare ad una presa di vero e proprio, ma non può funzionare fuori come farlo con ScalaMock.

Il mio codice di prova è simile al seguente:

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

Chiaramente che non compilerà perché SocketClient aspetta un percorso alla presa come argomento, ma non posso chiamare mock[SocketClient(s)] perché non è un tipo e posso 't chiamare mock[SocketClient](s) perché mock non accetta gli argomenti del tipo passati come se fossero propri argomenti.

Quindi, come posso scrivere una simulazione di fabbrica SocketClient per passare al mio scanner? Non riesco nemmeno a capire come prendere in giro una classe che prende argomenti!

+0

Sono l'autore di ScalaMock. Quale versione di Scala e quale versione di ScalaMock stai usando? Le risposte sono diverse per ScalaMock2 rispetto a ScalaMock3. –

+0

Scala Mock 3 con Scala 2.10.0 – jangoolie

risposta

3

L'intuizione è che ciò che è necessario prendere in giro è socketClientFactory. E quindi configurarlo per restituire un finto SocketClient.

Dato:

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 
} 

(nota a margine - il tuo valore di default per confPath non può mai essere utilizzato perché non c'è valore predefinito per socketClientFactory).

allora questo dovrebbe iniziare (questo è con Scala 2.9.x e ScalaMock2 - 2.10.x con ScalaMock3 sarà leggermente diverso, ma non tanto):

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) 
    } 
} 

Per completezza, ecco la stessa prova in Scala 2.10.0 e 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) 
    } 
} 
+0

Non sono sicuro di come questo superi il fatto che SocketClient accetta 1 argomento. Non posso scrivere: val mockClient = finte [SocketClient] mockFactory.expects ("qualche nome Socket") ritorno (mockClient) Perché finta [SocketClient] non verrà compilato.. Stai suggerendo di modificare SocketClient per non accettare argomenti o avere valori predefiniti per tutti gli argomenti? Anche se nessun valore predefinito ha senso. Grazie mille per aver risposto btw. – jangoolie

+1

Ah, scusa, mi è sfuggita quella prima volta. In questo momento, ScalaMock3 può solo simulare tratti e classi no-args. Ma se controlli SocketClient, dovresti comunque essere a posto - crea un tratto che definisce i metodi e lo implementa nella tua classe: tratto SocketClientBase; class SocketClient (...) estende SocketClientBase. Quindi puoi prendere in giro SocketClientBase e dovresti essere bravo? O mi sta sfuggendo qualcosa? –

+0

Anche di nota Anche se copio il codice esattamente non riesco a farlo compilare.Ottengo: metodo di overriding nestedSuites in tratto SuiteMixin di tipo => scala.collection.immutable.IndexedSeq [org.scalatest.Suite]; [errore] metodo nestedSuites in trait Suite di tipo => Elenco [org.scalatest.Suite] ha tipo incompatibile [error] class ScannerTest estende FunSuite con MockFactory { – jangoolie

Problemi correlati