2011-12-19 9 views
63

Sto cercando di incorporare ScalaTest nel mio progetto Java, sostituendo tutti i test JUnit di ScalaTests. A un certo punto, voglio controllare se l'iniettore di Guice inietta il tipo corretto. In Java, ho un test come questo:Come eseguire un'istanza di controllo con Scala (Test)

public class InjectorBehaviour { 
    @Test 
    public void shouldInjectCorrectTypes() { 
     Injector injector = Guice.createInjector(new ModuleImpl()); 
     House house = injector.getInstance(House.class); 

     assertTrue(house.door() instanceof WoodenDoor); 
     assertTrue(house.window() instanceof BambooWindow); 
     assertTrue(house.roof() instanceof SlateRoof); 
    } 
} 

Ma ho un problema a fare lo stesso con ScalaTest:

class InjectorSpec extends Spec { 
    describe("An injector") { 
     it("should inject the correct types") { 
      val injector = Guice.createInjector(new ModuleImpl) 
      val house = injector.getInstance(classOf[House]) 

      assert(house.door instanceof WoodenDoor) 
      assert(house.window instanceof BambooWindow) 
      assert(house.roof instanceof SlateRoof) 
     } 
    } 
} 

Esso denunce che il valore instanceof non è membro di porte/finestre/Tetto. Non posso usare instanceof in questo modo in Scala?

risposta

91

Scala non è Java. Scala non ha l'operatore instanceof invece ha un metodo parametrico chiamato isInstanceOf[Type].

+2

beh, questo in realtà non risponde alla domanda. ScalaTest ha il supporto integrato per il controllo dei tipi. Guarda la risposta di @ martin-g – maasg

+3

La mia risposta ha quasi 5 anni. La tecnica 'anInstance mustBe an [SomeClass]' mostrata da @ martin-g non esisteva allora (come afferma correttamente). Se volevi essere tecnico su questo, la mia risposta risponde perfettamente alla domanda dell'OP, che è: "Non posso usare l'istanza di questo modo in Scala?". Entrambi gli approcci funzionano fino ad oggi e sono quindi entrambe risposte corrette. Buona giornata. – agilesteel

+0

Come fare se "Digitare" è un tratto? – Lobo

28

Se si desidera essere meno JUnit-esque e se si desidera utilizzare gli abbinamenti di ScalaTest, è possibile scrivere il proprio correttore proprietà che corrisponde per tipo (cancellazione tipo barra).

Ho trovato questo thread per essere molto utile: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea

Si può quindi scrivere affermazioni come:

house.door should be (anInstanceOf[WoodenDoor]) 

invece di

assert(house.door instanceof WoodenDoor) 
+0

+1 Che sembra molto bello, e persino comprensibile per le persone non di programmazione (supponendo che sappiano cos'è un'istanza :-)). – helpermethod

+0

Se lo zucchero di sintassi è quello che stai cercando, con qualche refactoring potresti scrivere house.door dovrebbe essere (madeOf [Wood]) o house.door dovrebbe essere (madeOf [Bamboo]). –

+1

Vedi anche https://groups.google.com/d/topic/scalatest-users/HeOKgs5PC2o/discussion –

12

Le risposte attuali circa isInstanceOf [Tipo] e i consigli di junit sono buoni ma voglio aggiungere una cosa (per le persone che hanno ottenuto questa pagina in una capacità non legata alla junit). In molti casi la corrispondenza del modello scala si adatta alle tue esigenze. Lo raccomanderei in quei casi perché ti dà la typecasting gratuitamente e lascia meno spazio per errori.

Esempio:

OuterType foo = blah 
foo match { 
    case subFoo : SubType => { 
    subFoo.thingSubTypeDoes // no need to cast, use match variable 
    } 
    case subFoo => { 
    // fallthrough code 
    } 
} 
+0

Il metodo consigliato per verificare una corrispondenza di pattern in ScalaTest è usare 'inside (foo)' invece di 'foo match '. Vedi http://www.scalatest.org/user_guide/using_matchers#matchingAPattern –

2

Consolidare riferimento discussione ScalaTest di Guillaume (e un'altra discussione legata al da James Moore) in due metodi, aggiornato per ScalaTest 2.xe Scala 2.10 (per usare ClassTag piuttosto che manifesto):

import org.scalatest.matchers._ 
import scala.reflect._ 

def ofType[T:ClassTag] = BeMatcher { obj: Any => 
    val cls = classTag[T].runtimeClass 
    MatchResult(
    obj.getClass == cls, 
    obj.toString + " was not an instance of " + cls.toString, 
    obj.toString + " was an instance of " + cls.toString 
) 
} 

def anInstanceOf[T:ClassTag] = BeMatcher { obj: Any => 
    val cls = classTag[T].runtimeClass 
    MatchResult(
    cls.isAssignableFrom(obj.getClass), 
    obj.getClass.toString + " was not assignable from " + cls.toString, 
    obj.getClass.toString + " was assignable from " + cls.toString 
) 
} 
36

con ScalaTest 2.2.x (forse anche prima) si può usare: anInstance mustBe an[SomeClass]

+3

Questo è l'approccio raccomandato sulle versioni recenti di ScalaTests – maasg

+4

disponibile anche "a [Tipo]" in modo da poter essere grammaticalmente corretto;) – Samuel

+0

stavo cercando quello ! :) – Atais

0

io uso 2.11.8 a che fare con l'affermazione Coll riflessioni. La sintassi più recente è la seguente:

val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8) 
scores shouldBe a[Map[_, _]] 
+1

A causa della cancellazione non è possibile controllare i parametri di tipo 'Mappa'. Quello che hai scritto è lo stesso di scrivere 'punteggi dovrebbeBe a [Mappa [_, _]]'. Questo è citato qui: http://www.scalatest.org/user_guide/using_matchers#checkingAnObjectsClass –

Problemi correlati