Testing for type-ness

2,688 views
Skip to first unread message

David Pinn

unread,
Aug 30, 2010, 10:59:33 PM8/30/10
to scalatest-users
I'm really enjoying learning ScalaTest, and using it on my development
project. I'm very new to it, though. Would you please check the
following code to see if there's a better way to do it?

I'm trying to check that a certain Java method is returning an object
of a given type.

My test has the following code:

Handler.myEvent.get.getAction should be a (checkSession)

... and my CustomMatchers trait looks like this.

trait CustomMatchers {
class InstanceOfAction[A] extends BePropertyMatcher[Any] {
def apply(left: Any) = BePropertyMatchResult(left.isInstanceOf[A],
"instanceof")
}
val checkSession = new InstanceOfAction[CheckSession]
}

I thought that perhaps the ShouldMatchers would include something like
this, but I couldn't find it.

Bill Venners

unread,
Aug 31, 2010, 12:47:13 AM8/31/10
to scalate...@googlegroups.com
Hi David,

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

Bill Venners

unread,
Aug 31, 2010, 12:50:22 AM8/31/10
to scalate...@googlegroups.com
HI David,

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

David Pinn

unread,
Sep 1, 2010, 9:48:54 PM9/1/10
to scalatest-users
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.

On Aug 31, 2:50 pm, Bill Venners <b...@artima.com> wrote:
> HI David,
>
> 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(ShouldMatcher s.scala:2329)
>         at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(Sho uldMatchers.scala:871)
>         at org.scalatest.matchers.ShouldMatchers$AnyRefShouldWrapper.should(ShouldMatc hers.scala:1489)
> >        at org.scalatest.matchers.ShouldMatchers$AnyRefShouldWrapper.should(ShouldMatc hers.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(ShouldMatcher s.scala:2329)
> >        at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(Sho uldMatchers.scala:871)
> >        at org.scalatest.matchers.ShouldMatchers$StringShouldWrapper.should(ShouldMatc hers.scala:1081)

Bill Venners

unread,
Sep 1, 2010, 10:04:50 PM9/1/10
to scalate...@googlegroups.com
Hi David,

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

David Pinn

unread,
Sep 25, 2010, 12:55:22 AM9/25/10
to scalatest-users
I'd now like to apply the anInstanceOf[T] matcher to a collection, to
determine if the collection contains an instance of T. I'm having
trouble determining why it doesn't work; can you help?

scala> import org.scalatest.matchers._
import org.scalatest.matchers._

scala> import ShouldMatchers._
import ShouldMatchers._

scala> import collection.immutable.List
import collection.immutable.List

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> class Super
defined class Super

scala> class Sub extends Super
defined class Sub

scala> (new Sub) should be (anInstanceOf[Super])

scala> (List(new Sub)) should contain (anInstanceOf[Super])
<console>:16: error: overloaded method value should with alternatives:
(notWord:
org.scalatest.matchers.ShouldMatchers.NotWord)org.scalatest.matchers.ShouldMatchers.ResultOfNotWordForSeq[Sub,List[Sub]]
<and>
(haveWord:
org.scalatest.matchers.ShouldMatchers.HaveWord)org.scalatest.matchers.ShouldMatchers.ResultOfHaveWordForSeq[Sub]
<and>
(beWord:
org.scalatest.matchers.ShouldMatchers.BeWord)org.scalatest.matchers.ShouldMatchers.ResultOfBeWordForAnyRef[List[Sub]]
<and>
(rightMatcher: org.scalatest.matchers.Matcher[List[Sub]])Unit
cannot be applied to
(org.scalatest.matchers.Matcher[Iterable[java.lang.Object with
org.scalatest.matchers.BePropertyMatcher[AnyRef]]])
(List(new Sub)) should contain (anInstanceOf[Super])
^

Bill Venners

unread,
Sep 25, 2010, 4:50:45 PM9/25/10
to scalate...@googlegroups.com
Hi David,

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

David Pinn

unread,
Sep 25, 2010, 5:55:14 PM9/25/10
to scalatest-users
Thanks again for your help. I like your idea of the
someValueSatisfying matcher.

I think that your interim solution probably should used 'exists'
rather than 'contains' as in:

(List(new Sub) exists (_.isInstanceOf[Super])) should be (true)

On Sep 26, 6:50 am, Bill Venners <b...@artima.com> wrote:
> Hi David,
>
> > org.scalatest.matchers.ShouldMatchers.BeWord)org.scalatest.matchers.ShouldM atchers.ResultOfBeWordForAnyRef[List[Sub]]
> ...
>
> read more »

Bill Venners

unread,
Sep 25, 2010, 6:15:59 PM9/25/10
to scalate...@googlegroups.com
Hi David,

Yes, you're right about exists. I didn't have time to try it before sending.

Thanks.

Bill

Reply all
Reply to author
Forward
0 new messages