2011-12-19 15 views
63

Próbuję włączyć ScalaTest do mojego projektu Java, zastępując wszystkie testy JUnit przez ScalaTests. W pewnym momencie chcę sprawdzić, czy wtryskiwacz Guice wstrzykuje właściwy typ. W Javie mam test takiego:Jak wykonać test instanceof z 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); 
    } 
} 

Ale mam problem robi to samo z 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) 
     } 
    } 
} 

skarg, że wartość instanceof nie jest członkiem drzwi/okna/Dach. Nie mogę użyć instanceof w ten sposób w Scali?

Odpowiedz

91

Scala to nie Java. Scala po prostu nie ma operatora instanceof zamiast tego ma parametryczną metodę o nazwie isInstanceOf[Type].

+2

cóż, to tak naprawdę nie odpowiada na pytanie. ScalaTest ma wbudowaną obsługę sprawdzania typu. Zobacz odpowiedź z @ martin-g – maasg

+3

Moja odpowiedź jest prawie 5 lat. Technika 'anInvent mustBe an [SomeClass]' pokazana przez @ martin-g nie istniała wtedy (jak słusznie stwierdza). Jeśli chcesz być na to techniczny, moja odpowiedź doskonale odpowiada na pytanie OP, które brzmi: "Czy nie mogę użyć instanceof w ten sposób w Scali?". Oba podejścia działają od dzisiaj i dlatego są poprawnymi odpowiedziami. Miłego dnia. – agilesteel

+0

Jak to zrobić, jeśli "Typ" to cecha? – Lobo

28

Jeśli chcesz być mniej JUnit-esque i chcesz korzystać z masek ScalaTest, możesz napisać własny matcher właściwości, który pasuje do typu (wymazywanie typu kreskowego).

Znalazłem ten wątek się być całkiem przydatne: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea

Następnie można napisać twierdzeń typu:

house.door should be (anInstanceOf[WoodenDoor]) 

zamiast

assert(house.door instanceof WoodenDoor) 
+0

+1 To wygląda bardzo ładnie, a nawet zrozumiałe dla osób nie programujących (zakładając, że wiedzą, co to jest instancja :-)). – helpermethod

+0

Jeśli cukier składniowy jest tym, czego szukasz, z pewnym refaktoryzacją możesz napisać house.door powinno być (madeOf [Wood]) lub house.door powinno być (madeOf [Bamboo]). –

+1

Zobacz także https://groups.google.com/d/topic/scalatest-users/HeOKgs5PC2o/discussion –

12

Obecne odpowiedzi dotyczące isInstanceOf [typ] i dobre porady są dobre, ale chcę dodać jedną rzecz (dla osób, które dostały się na tę stronę w sposób niezwiązany z junitem). W wielu przypadkach dopasowanie do wzoru scala będzie pasować do twoich potrzeb. Polecam go w tych przypadkach, ponieważ daje on darmowy typ i daje mniej miejsca na błędy.

przykład:

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

Zalecanym sposobem przetestowania dopasowania wzorca w ScalaTest jest użycie 'inside (foo)' zamiast 'foo match '. Zobacz http://www.scalatest.org/user_guide/using_matchers#matchingAPattern –

2

Konsolidacja odniesienia ScalaTest dyskusji Guillaume (oraz inny dyskusji związanej z James Moore) w dwóch metod aktualizowana ScalaTest 2.x i Skala 2,10 (użyć ClassTag zamiast oczywisty)

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

z Scalatest 2.2.x (być może nawet wcześniej) można użyć: anInstance mustBe an[SomeClass]

+3

To jest zalecane podejście do najnowszych wersji ScalaTests – maasg

+4

dostępne również 'a [Type]', dzięki czemu można być poprawne gramatycznie;) – Samuel

+0

Szukałem tego ! :) – Atais

0

używam 2.11.8 zrobić twierdzenie z Coll sekcje. Nowsza składnia jest następująca:

+1

Z powodu skasowania nie można sprawdzić parametrów typu "Mapa". To, co napisałeś, jest takie samo, jak pisanie "scoresBe a [Map [_, _]]". Jest to wspomniane tutaj: http://www.scalatest.org/user_guide/using_matchers#checkingAnObjectsClass –