You could do it with a type parameter if you use a manifest, like this:
scala> import org.scalatest.matchers.ShouldMatchers._
import org.scalatest.matchers.ShouldMatchers._
scala> import org.scalatest.matchers.BePropertyMatcher
import org.scalatest.matchers.BePropertyMatcher
scala> import org.scalatest.matchers.BePropertyMatchResult
import org.scalatest.matchers.BePropertyMatchResult
scala> def anInstanceOf[T](implicit manifest: Manifest[T]) = {
| val clazz = manifest.erasure.asInstanceOf[Class[T]]
| new BePropertyMatcher[AnyRef] { def apply(left: AnyRef) =
BePropertyMatchResult(left.getClass.isAssignableFrom(clazz), "an
instance of " + clazz.getName) }
| }
anInstanceOf: [T](implicit manifest: Manifest[T])java.lang.Object with
org.scalatest.matchers.BePropertyMatcher[AnyRef]
scala> "hi" should be (anInstanceOf[String])
scala> (new java.util.Date) should be (anInstanceOf[String])
org.scalatest.TestFailedException: Mon Aug 30 21:43:40 PDT 2010 was
not an instance of java.lang.String
at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:148)
at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2329)
at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(ShouldMatchers.scala:871)
at org.scalatest.matchers.ShouldMatchers$AnyRefShouldWrapper.should(ShouldMatchers.scala:1489)
at .<init>(<console>:21)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java...
scala> "ouch" should be (anInstanceOf[Int])
org.scalatest.TestFailedException: "ouch" was not an instance of int
at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:148)
at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2329)
at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(ShouldMatchers.scala:871)
at org.scalatest.matchers.ShouldMatchers$StringShouldWrapper.should(ShouldMatchers.scala:1081)
at .<init>(<console>:21)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMeth...
Currently there's no special syntax for this in ScalaTest matchers. I
was already planning on adding a matcher for isInstanceOf, so in a
future release you'll no longer need to use your custom
BePropertyMatcher.
Thanks.
Bill
> --
> You received this message because you are subscribed to the Google
> Groups "scalatest-users" group.
> To post to this group, send email to scalate...@googlegroups.com
> To unsubscribe from this group, send email to
> scalatest-use...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/scalatest-users?hl=en
> ScalaTest itself, and documentation, is available here:
> http://www.artima.com/scalatest
>
--
Bill Venners
Artima, Inc.
http://www.artima.com
Ack. Strike that, I had my classes reversed. It should be:
scala> class Super
defined class Super
scala> class Sub extends Super
defined class Sub
scala> def anInstanceOf[T](implicit manifest: Manifest[T]) = {
| val clazz = manifest.erasure.asInstanceOf[Class[T]]
| new BePropertyMatcher[AnyRef] { def apply(left: AnyRef) =
BePropertyMatchResult(clazz.isAssignableFrom(left.getClass), "an
instance of " + clazz.getName) }
| }
anInstanceOf: [T](implicit manifest: Manifest[T])java.lang.Object with
org.scalatest.matchers.BePropertyMatcher[AnyRef]
scala> (new Sub) should be (anInstanceOf[Super])
scala> (new Super) should be (anInstanceOf[Sub])
org.scalatest.TestFailedException: Super@1f567ee3 was not an instance of Sub
at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:148)
at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2329)
at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(ShouldMatchers.scala:871)
at org.scalatest.matchers.ShouldMatchers$AnyRefShouldWrapper.should(ShouldMatchers.scala:1489)
at .<init>(<console>:23)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.Delega...
Thanks.
Bill
On Wed, Sep 1, 2010 at 6:48 PM, David Pinn <dp...@byandlarge.net> wrote:
> That sent me back to the books. implicit! manifests! oh my! Got it all
> sorted now, and your code sample did the trick, of course. Thanks very
> much for your support, Bill.
>
Sure thing. I'll add "be anInstanceOf[T]" as a matcher soon, and the
syntax will look the same as your custom one, so you won't need to use
your custom BePropertyMatcher anymore, but you're usages of it should
work unchanged. I expect I'll put the new matchers not in the next
release, which I want to get very out soon, but the release after
next.
Thanks.
Bill
Sorry for the half-day delay in getting back. The contain (<value>)
matcher in ScalaTest (almost) always checks whether the collection
contains the specified value. So you're trying to check whether the
BePropertyMatcher[AnyRef] instance is inside that list, which doesn't
type check, because the element type of the list is Sub, not
BePropertyMatcher[AnyRef]. Another matcher I have been considering
adding is one that would help you here. It will look like:
List(new Sub) should contain someValueSatisfying (_.isInstanceOf[Super])
For now you an do this:
(List(new Sub) contains (_.isInstanceOf[Super])) should be (true)
However, you've actually made a very interesting suggestion. Right now
contain does actually have a different meaning if it is used on a map
and followed by key or value.
map should contain key 'a'
map should contain value 3
And I have been thinking about having these be special uses of contain also:
a should contain theSameElementsAs b
a should contain theSameSequenceAs b
a should contain someValueSatisfying p
(These are all matchers that people have requested.) But if we're
going to have so many special cases for contain, why not let
BePropertyMatchers work like you thought they would work here. If you
say:
List(new Sub) should contain (anInstanceOf[Super])
It would look for an element inside the list for which the
BePropertyMatcher succeeds. I'll add that to the list of new matchers
being considered.
Thanks very much for the question. Using BePropertyMatchers in this
way hadn't occurred to me.
Bill
Yes, you're right about exists. I didn't have time to try it before sending.
Thanks.
Bill