Comment faire une instance de vérification avec Scala (test)


100

J'essaye d'incorporer ScalaTest dans mon projet Java; remplacer tous les tests JUnit par des ScalaTests. À un moment donné, je veux vérifier si l'injecteur de Guice injecte le bon type. En Java, j'ai un test comme celui-ci:

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

Mais j'ai un problème à faire de même avec 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)
        }
    }
}

Il se plaint que la valeur instanceofn'est pas membre de Door/ Window/ Roof. Puis-je utiliser instanceofcette méthode dans Scala?

Réponses:


114

Scala n'est pas Java. Scala n'a tout simplement pas l'opérateur à la instanceofplace, il a une méthode paramétrique appelée isInstanceOf[Type].

Vous pourriez également apprécier de regarder un cours intensif ScalaTest .


6
eh bien, cela ne répond pas vraiment à la question. ScalaTest a un support intégré pour la vérification de type. Voir la réponse de @ martin-g
maasg

Comment faire si "Type" c'est un trait?
Lobo

Je ne sais pas si je comprends bien, mais il devrait être le même: isInstanceOf[TraitName].
agilesteel

88

Avec Scalatest 2.2.x (peut-être même plus tôt), vous pouvez utiliser:

anInstance mustBe a[SomeClass]

4
C'est l'approche recommandée sur les versions récentes de ScalaTests
maasg le

6
également disponible a[Type]pour que vous puissiez être grammaticalement correct;)
Samuel

Je cherchais ça! :)
Atais le

22
tiger shouldBe a [Tiger]est la syntaxe actuelle scalatest.org/at_a_glance/FlatSpec
jhegedus

2
@jhegedus mustBeest également correct, si vous utilisez doc.scalatest.org/3.0.1/#org.scalatest.MustMatchers que vous voulez pour FreeSpec.
Tobi

30

Si vous voulez être moins JUnit-esque et si vous voulez utiliser les matchers de ScalaTest, vous pouvez écrire votre propre correspondance de propriété qui correspond au type (effacement du type de barre).

J'ai trouvé ce fil assez utile: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea

Vous pouvez ensuite écrire des assertions comme:

house.door should be (anInstanceOf[WoodenDoor])

au lieu de

assert(house.door instanceof WoodenDoor)

+1 Cela a l'air très agréable, et même compréhensible pour les non-programmeurs (en supposant qu'ils savent ce qu'est une instance :-)).
helpermethod

Si le sucre de syntaxe est ce que vous recherchez, avec un peu de refactorisation, vous pourrez peut-être écrire que house.door devrait être (madeOf [Wood]) ou house.door devrait être (madeOf [Bamboo]).
Guillaume Belrose


16

Les réponses actuelles à propos de isInstanceOf [Type] et des conseils junit sont bonnes, mais je veux ajouter une chose (pour les personnes qui sont arrivées sur cette page dans une capacité non liée à junit). Dans de nombreux cas, la correspondance de motifs scala répondra à vos besoins. Je le recommanderais dans ces cas, car il vous donne le typage gratuitement et laisse moins de place à l'erreur.

Exemple:

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

La méthode recommandée pour tester une correspondance de modèle dans ScalaTest est d'utiliser à la inside(foo)place de `foo match). Voir scalatest.org/user_guide/using_matchers#matchingAPattern
Rich Dougherty

3

Consolidation de la référence de discussion ScalaTest de Guillaume (et d'une autre discussion liée à par James Moore) en deux méthodes, mises à jour pour ScalaTest 2.x et Scala 2.10 (pour utiliser ClassTag plutôt que manifest):

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

2

J'utilise 2.11.8 pour faire l'assertion avec des collections. La nouvelle syntaxe est la suivante:

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

3
En raison de l'effacement, vous ne pouvez pas vérifier les Mapparamètres de type de. Ce que vous avez écrit équivaut à écrire scores shouldBe a[Map[_, _]]. Ceci est mentionné ici: scalatest.org/user_guide/using_matchers#checkingAnObjectsClass
Rich Dougherty
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.