ChatGPT解决这个技术问题 Extra ChatGPT

Assert an object is a specific type

Is it possible in JUnit to assert an object is an instance of a class? For various reasons I have an object in my test that I want to check the type of. Is it a type of Object1 or a type of Object2?

Currently I have:

assertTrue(myObject instanceof Object1);
assertTrue(myObject instanceof Object2);

This works but I was wondering if there is a more expressive way of doing this.

For example something like:

assertObjectIsClass(myObject, Object1);

I could do this:

assertEquals(myObject.class, Object1.getClass());

Is there a specific assert method that allows me to test a type of an object in a more elegant, fluid manner?

Are you aware that assertTrue(myObject instanceof Object1); and assertEquals(myObject.class, Object1.getClass()); are actually different tests? The first accepts myObject being an instance of a subclass of Object1, the later doesn't.
@ammoQ Very good point. I didnt think of subclasses. Thanks for the clarifaction
as maba points out, consider using Hamcrest. This is more than just so that you have a better working test. Hamcrest also provides much better logging of the failure than standard assertTrue. assertTrue would just say expected true got false, Hamcrest would say expected instanced of XYZ, got instance of ABC

m
maba

You can use the assertThat method and the Matchers that comes with JUnit.

Take a look at this link that describes a little bit about the JUnit Matchers.

Example:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Test:

import org.junit.Test;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;

/**
 * @author maba, 2012-09-13
 */
public class InstanceOfTest {

    @Test
    public void testInstanceOf() {
        SubClass subClass = new SubClass();
        assertThat(subClass, instanceOf(BaseClass.class));
    }
}

Here is the link to the Matcher being used: hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
FYI, MatcherAssert.assertThat behaves better (provides better logging in the case of errors) than Assert.assertThat. I recommend using it instead. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
That's a trivial assertion and would be a compile error if not true in the example! Usually you want to go down the class hierarchy with instanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, but it doesn't compile because SubClass is not ? super BaseClass.
@TWiStErRob I don't understand what you are trying to say here... Try to change the instanceOf(BaseClass.class) to instanceOf(String.class) and you'll see that it compile just fine but there will be an AssertionError thrown.
@maba, he's talking about isA for some reason, which captures the class, it accepts Class<T> instead of Class<?> (which is what instanceOf does). Since it captures the class, it would be a compile time error to do isA with a class incompatible to the instance. github.com/hamcrest/JavaHamcrest/issues/39
C
Carmageddon

Since assertThat which was the old answer is now deprecated, I am posting the correct solution:

assertTrue(objectUnderTest instanceof TargetObject);


if objectUnderTest is a subclass of TargetObject, this will still result into true right? And I think you want to test the actual type.
I feel this is NOT the correct answer. The original question was asking for something that specifically checks on the exact type of the object. This solutions does not that (as mentioned by @EircG above) and it has even been provided by the user originally asking the question, so definitely not the "correct" answer imo. For the correct answer, please check the Franklin Yu answer.
Well, it has the downside which @EricG mentioned yes, about Franklin's answer - I just looked at it, and it didnt make sense to me so I just tested in my project with Junit5 - it is wrong!! there is no such syntax for instanceof , nor a method called InstanceOf! He is totally wrong. I stand by my answer still, and as evidenced, it was helpful to at least 30 people who upvoted it! (I assume you downvoted).
@kekko12 My answer doesn’t check the exact type either; it accepts subclass similar to this answer. I have updated my answer to address it; sorry that I didn’t notice this part in question. I think exact equality isn’t included in most assertion library because it isn’t frequently used.
@Carmageddon The answer from Franlin Yu does work fine if you use hamcrest assertion importing: ``` import static org.hamcrest.CoreMatchers.instanceOf; ``` ss per his code samples. I do admit though I overlooked at Franklin answer and in fact, these 2 answers are functionally equivalent, so I guess it is just a matter of preference in the end.
F
Franklin Yu

Solution for JUnit 5

The documentation says:

However, JUnit Jupiter’s org.junit.jupiter.Assertions class does not provide an assertThat() method like the one found in JUnit 4’s org.junit.Assert class which accepts a Hamcrest Matcher. Instead, developers are encouraged to use the built-in support for matchers provided by third-party assertion libraries.

Example for Hamcrest:

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.jupiter.api.Test;

class HamcrestAssertionDemo {

    @Test
    void assertWithHamcrestMatcher() {
        SubClass subClass = new SubClass();
        assertThat(subClass, instanceOf(BaseClass.class));
    }

}

Example for AssertJ:

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

class AssertJDemo {

    @Test
    void assertWithAssertJ() {
        SubClass subClass = new SubClass();
        assertThat(subClass).isInstanceOf(BaseClass.class);
    }

}

Note that this assumes you want to test behaviors similar to instanceof (which accepts subclasses). If you want exact equal type, I don’t see a better way than asserting the two class to be equal like you mentioned in the question.


In a sense, the original assertThat() is deferred to Hamcrest, so that JUnit also works with third-party assertion libraries.
I just tested this answer, it is NOT correct and leads to multiple compilation errors: Illegal start of expression, illegal start of type, ';' expected... In other words, your second parameter to the assertThat matcher, CANNOT be "instanceof (BaseClass.class)"! In fact, you didnt even type that correctly, the syntax you used is slightly different - "InstanceOf(" - as a function call! There is no such function actually... was it even tested by anyone? It seems to have been manually typed without any tests
@Carmageddon I provided two answers, one for Hamcrest and the other for AssertJ. Which one are you talking about?
@Carmageddon I suspect that you are talking about the Hamcrest example and you miss-typed instanceOf as instanceof (mind the case). instanceOf is a function while instanceof is a Java keyword.
I referred to the Hamcrest one of course, and I tried both keyword AND as a function after I noticed thats how you wrote it - there is no such function...
N
Naruto Sempai

Solution for JUnit 5 for Kotlin!

Example for Hamcrest:

import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
import org.junit.jupiter.api.Test

class HamcrestAssertionDemo {

    @Test
    fun assertWithHamcrestMatcher() {
        val subClass = SubClass()
        MatcherAssert.assertThat(subClass, CoreMatchers.instanceOf<Any>(BaseClass::class.java))
    }

}

Example for AssertJ:

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class AssertJDemo {

    @Test
    fun assertWithAssertJ() {
        val subClass = SubClass()
        assertThat(subClass).isInstanceOf(BaseClass::class.java)
    }

}

use ` assertThat(actualException, not(instanceOf(BaseClass.class))); ` for negative test.
M
Mahmoud Mabrok

Solution for JUnit for Kotlin

What worked for me:

assert(obj is ClassName)

for exmaple

assert(obj is User)

NOTE: assert is coming from AssertionsJVM.kt file


g
gla3dr

Experimental Solution for JUnit 5.8

In Junit 5.8, the experimental assertInstanceOf() method was added, so you don't need Hamcrest or AssertJ anymore. The solution is now as simple as:

import static org.junit.jupiter.api.Assertions.assertInstanceOf;

import org.junit.Test;

public class InstanceOfTest {

    @Test
    public void testInstanceOf() {
        SubClass subClass = new SubClass();
        assertInstanceOf(BaseClass.class, subClass);
    }
}