Cómo hacer una instancia de verificación con Scala (prueba)

100

Estoy intentando incorporar ScalaTest en mi proyecto Java; reemplazando todas las pruebas JUnit con ScalaTests. En un momento, quiero comprobar si el inyector de Guice inyecta el tipo correcto. En Java, tengo una prueba como esta:

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

Pero tengo un problema para hacer lo mismo 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)
        }
    }
}

Se queja de que el valor instanceofno es miembro de Door/ Window/ Roof. ¿No puedo usar instanceofesa forma en Scala?

método de ayuda
fuente

Respuestas:

114

Scala no es Java. Scala simplemente no tiene el operadorinstanceof sino que tiene un método paramétrico llamado isInstanceOf[Type].

También puede disfrutar viendo un curso intensivo ScalaTest .

agilesteel
fuente
6
bueno, eso no responde realmente a la pregunta. ScalaTest tiene soporte incorporado para verificación de tipo. Vea la respuesta de @ martin-g
maasg
¿Cómo hacerlo si "Tipo" es un rasgo?
Lobo
No estoy seguro si he entendido bien, pero debe ser la misma: isInstanceOf[TraitName].
agilesteel
88

Con Scalatest 2.2.x (tal vez incluso antes) puede usar:

anInstance mustBe a[SomeClass]
martin-g
fuente
4
Este es el enfoque recomendado en versiones recientes de ScalaTests
maasg
6
también disponible a[Type]para que puedas ser gramaticalmente correcto;)
Samuel
¡Estaba buscando eso! :)
Atais
22
tiger shouldBe a [Tiger]es la sintaxis actual scalatest.org/at_a_glance/FlatSpec
jhegedus
2
@jhegedus mustBetambién es correcto, si usa doc.scalatest.org/3.0.1/#org.scalatest.MustMatchers que desea para FreeSpec.
Tobi
30

Si desea ser menos JUnit-esque y si desea utilizar los comparadores de ScalaTest, puede escribir su propio comparador de propiedades que coincida con el tipo (borrado de tipo de barra).

Encontré este hilo bastante útil: http://groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea

Luego puede escribir afirmaciones como:

house.door should be (anInstanceOf[WoodenDoor])

en vez de

assert(house.door instanceof WoodenDoor)
Guillaume Belrose
fuente
+1 Eso se ve muy bien, e incluso comprensible para las personas que no programan (suponiendo que sepan qué es una instancia :-)).
helpermethod
Si lo que busca es azúcar de sintaxis, con un poco de refactorización podría escribir house.door debería ser (madeOf [Wood]) o house.door debería ser (madeOf [Bamboo]).
Guillaume Belrose
16

Las respuestas actuales sobre isInstanceOf [Type] y junit advice son buenas, pero quiero agregar una cosa (para las personas que llegaron a esta página en una capacidad no relacionada con junit). En muchos casos, la coincidencia de patrones de Scala se adaptará a sus necesidades. Lo recomendaría en esos casos porque te da el encasillado gratis y deja menos margen de error.

Ejemplo:

OuterType foo = blah
foo match {
  case subFoo : SubType => {
    subFoo.thingSubTypeDoes // no need to cast, use match variable
  }
  case subFoo => {
    // fallthrough code
  }
}
alexbobp
fuente
La forma recomendada de probar una coincidencia de patrones en ScalaTest es usar en inside(foo)lugar de `foo match). Ver scalatest.org/user_guide/using_matchers#matchingAPattern
Rich Dougherty
3

Consolidar la referencia de discusión ScalaTest de Guillaume (y otra discusión vinculada por James Moore) en dos métodos, actualizados para ScalaTest 2.xy Scala 2.10 (para usar ClassTag en lugar de manifiesto):

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
  )
}
Raman
fuente
2

Utilizo 2.11.8 para hacer la aserción con colecciones. La sintaxis más nueva es la siguiente:

val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8)
scores shouldBe a[Map[_, _]] 
aristotll
fuente
3
Debido al borrado, no puede verificar los Mapparámetros del tipo. Lo que escribiste es lo mismo que escribir scores shouldBe a[Map[_, _]]. Esto se menciona aquí: scalatest.org/user_guide/using_matchers#checkingAnObjectsClass
Rich Dougherty