tags:

views:

323

answers:

5

Hi, I'm creating a test platform for a protocol project based on Apache MINA. In MINA when you receive packets the messageReceived() method gets an Object. Ideally I'd like to use a JUnit method assertClass(), however it doesn't exist. I'm playing around trying to work out what is the closest I can get. I'm trying to find something similar to instanceof.

Currently I have:

public void assertClass(String msg, Class expected, Object given) {
if(!expected.isInstance(given)) Assert.fail(msg);
}

To call this:

assertClass("Packet type is correct", SomePacket.class, receivedPacket);

This works without issue, however in experimenting and playing with this my interest was peaked by the instanceof operator.

if (receivedPacket instanceof SomePacket) { .. }

How is instanceof able to use SomePacket to reference the object at hand? It's not an instance of an object, its not a class, what is it?! Once establishing what type SomePacket is at that point is it possible to extend my assertClass() to not have to include the SomePacket.class argument, instead favouring SomePacket?

A: 

SomePacket is a type, like this:

 SomePacket something = null;

You cannot reference it directly at runtime in the way that you want. The class object is the only way to go that I know of.

Yishai
A: 

FYI, you could check

if(given == null || given.getClass() != expected)

to check if the class of given is exactly the class expected, not just assignment-compatible.
I'd call this one assertClass and your original suggestion assertInstance or assertInstanceOf.

In response to the comment:
My answer was meant as a general tip, not as an answer to your original question. I added an "FYI" to make that clearer ;)

Depending on what exactly you want, both ways may be reasonable.

In the following example

public class Base {}
public interface Ifc {}

public class A{} extends Base implements Ifc
public class B{} extends Base

the behavior of the methods above would be like this

A a=new A();
B b=new B();

assertClass(A.class, a);
assertClass(Base.class, a); // fails, a.getClass() != Base.class
assertClass(Ifc.class, a); // fails, a.getClass() != Ifc.class
assertClass(B.class, b);
assertClass(Base.class, b); // fails, b.getClass() != Base.class
assertClass(Ifc.class, b); // fails, b.getClass() != Ifc.class

assertInstance(A.class, a);
assertInstance(Base.class, a); // works
assertInstance(Ifc.class, a); // works
assertInstance(B.class, b);
assertInstance(Base.class, b); // works
assertInstance(Ifc.class, b); // fails, B does not implement Ifc

Most likely you'll want to check with your method.
But if you want to validate the exact class, e.g. to make sure that it's not proxied or that it's not an extending class, my suggestion would be the way to do that.

Huxi
The accuracy of the name of the method isn't what I'm trying to get an answer to. Perhaps my list of questions at the end were not clear. I'm more interested in how instanceof can reference the object as it does. I'm beginning to think the JVM does something like this: if (o instanceof Obj)== if (o.getClass().equals(Obj.class))?
Mike
Huxi
A: 

Why don't you just use assertEquals?

assertEquals(SomePacket.class, given.getClass());
Cem Catikkas
The question is more of an interest - how does instanceof reference the class directly as it does?FWIW I probably will end up having to use assertEquals(). The main problem is the potential for error. It is easy to forget to .getClass(). Writing multiple methods with one which takes an Object and calls .getClass() will clearly solve this niggle though.
Mike
+1  A: 

The argument to instanceof is a class/interface name, and it is implemented directly as a JVM instruction. As such it is pretty efficient.

http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html#instanceof

One advantage of instanceof instead of comparing the classes is that instanceof will still work if the class has been proxied.

It will also work if the object being checked is null.

objects
Thanks! I guess it is as I thought - I cannot duplicate a similar result and must call the .getClass() and compare it that way.
Mike
+1  A: 

Please take a look at the Hamcrest matchers, now included in JUnit. What you want is something like:

assertThat(receivedPacket, instanceOf(SomePacket.class));

That does everything you need, including a decent error message

Steve Freeman
Answers a different question - but it's an answer :) Thanks Steve.
Mike
it should be `assertThat(receivedPacket, instanceOf(SomePacket.class));` (notice the `.class`)
robinst
Corrected, thanks
Steve Freeman