如何用Scala做一个实例检查(Test)
我试图将ScalaTest整合到我的Java项目中,用ScalaTestsreplace所有的JUnittesting。 有一次,我想检查Guice的注射器是否注入了正确的types。 在Java中,我有这样的testing:
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); } }
但是我在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) } } }
它抱怨价值instanceof不是门/窗/屋顶的成员。 我不能在Scala中使用instanceof吗?
Scala不是Java。 Scala只是没有运算符instanceof
而是有一个名为isInstanceOf[Type]
的参数方法。
如果你想减lessJUnit-esque,如果你想使用ScalaTest的匹配器,你可以编写自己的属性匹配types(条形擦除)的匹配器。
我发现这个线程非常有用: http : //groups.google.com/group/scalatest-users/browse_thread/thread/52b75133a5c70786/1440504527566dea?#1440504527566dea
然后你可以写下如下的断言:
house.door should be (anInstanceOf[WoodenDoor])
代替
assert(house.door instanceof WoodenDoor)
使用Scalatest 2.2.x(甚至更早),您可以使用: anInstance mustBe an[SomeClass]
目前关于isInstanceOftypes的答案和junit的build议是好的,但是我想补充一点(对于以非junit相关的身份进入这个页面的人)。 在许多情况下,scala模式匹配将适合您的需求。 我会在这种情况下推荐它,因为它给你免费的types转换,并留下更less的错误空间。
例:
OuterType foo = blah foo match { case subFoo : SubType => { subFoo.thingSubTypeDoes // no need to cast, use match variable } case subFoo => { // fallthrough code } }
将Guillaume的ScalaTest讨论参考(和James Moore链接的另一个讨论)合并为两个方法,ScalaTest 2.x和Scala 2.10更新(使用ClassTag而不是清单):
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.11.8做集合的断言。 较新的语法如下所示:
val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8) scores shouldBe a[Map[_, _]]