Afirmar que um objeto é um tipo específico

195

É possível no JUnit afirmar que um objeto é uma instância de uma classe? Por várias razões, tenho um objeto em meu teste no qual desejo verificar o tipo. É um tipo de Object1 ou um tipo de Object2?

Atualmente tenho:

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

Isso funciona, mas eu queria saber se existe uma maneira mais expressiva de fazer isso.

Por exemplo, algo como:

assertObjectIsClass(myObject, Object1);

Eu poderia fazer isso:

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

Existe um método de afirmação específico que me permita testar um tipo de objeto de uma maneira mais elegante e fluida?

RNJ
fonte
15
Você está ciente disso assertTrue(myObject instanceof Object1);e assertEquals(myObject.class, Object1.getClass());é realmente testes diferentes? O primeiro aceita myObject como uma instância de uma subclasse de Object1, o posterior não.
Erich Kitzmueller
@ammoQ Muito bom ponto. Eu não pensei em subclasses. Obrigado pela clarifaction
RNJ
1
como maba aponta, considere usar o Hamcrest. Isso é mais do que apenas para que você tenha um teste de trabalho melhor. O Hamcrest também fornece um registro de falha muito melhor que o padrão assertTrue. assertTruediria apenas expected true got false, Hamcrest diriaexpected instanced of XYZ, got instance of ABC
John B

Respostas:

253

Você pode usar o assertThatmétodo e os Matchers que acompanham o JUnit.

Dê uma olhada neste link que descreve um pouco sobre os JUnit Matchers.

Exemplo:

public class BaseClass {
}

public class SubClass extends BaseClass {
}

Teste:

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));
    }
}
maba
fonte
4
Aqui está o link para o Matcher que está sendo usado: hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B
3
Para sua informação, MatcherAssert.assertThat se comporta melhor (fornece um registro melhor no caso de erros) que Assert.assertThat. Eu recomendo usá-lo. hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/…
John B
13
Essa é uma afirmação trivial e seria um erro de compilação, se não for verdade no exemplo! Normalmente, você quer ir para baixo na hierarquia de classe com instanceof: BaseClass subClass = new SubClass(); assertThat(subClass, isA(SubClass.class));, mas ele não compilar porque SubClassnão é ? super BaseClass.
TWiStErRob
3
@TWiStErRob Eu não entendo o que você está tentando dizer aqui ... Tente alterar o instanceOf(BaseClass.class)para instanceOf(String.class)e você verá que ele compila muito bem, mas haverá um AssertionError lançado.
maba 3/09/14
1
@ maba, ele está falando sobre isA por algum motivo, que captura a classe, aceita em Class<T>vez de Class<?>(que é o que instanceOf faz). Como captura a classe, seria um erro de tempo de compilação executar isA com uma classe incompatível com a instância. github.com/hamcrest/JavaHamcrest/issues/39
Vsevolod Golovanov
46

Como assertThatqual foi a resposta antiga agora está obsoleta, estou postando a solução correta:

assertTrue(objectUnderTest instanceof TargetObject);

Carmageddon
fonte
2
se objectUnderTest for uma subclasse de TargetObject, isso ainda resultará em truecerto? E acho que você deseja testar o tipo real.
EricG
Eu sinto que esta não é a resposta correta. A pergunta original estava pedindo algo que verifique especificamente o tipo exato do objeto. Essa solução não é essa (conforme mencionado pelo @EircG acima) e até foi fornecida pelo usuário originalmente fazendo a pergunta, então definitivamente não é a resposta "correta". Para a resposta correta, verifique a resposta de Franklin Yu.
precisa saber é o seguinte
Bem, tem a desvantagem que a @EricG mencionou que sim, sobre a resposta de Franklin - eu apenas olhei para ela e não fazia sentido para mim, então apenas testei no meu projeto com o Junit5 - está errado! não existe essa sintaxe para instanceof, nem um método chamado InstanceOf! Ele está totalmente errado. Ainda mantenho minha resposta e, como evidenciado, foi útil para pelo menos 30 pessoas que a votaram! (Presumo que você tenha votado mal).
Carmageddon
@ kekko12 Minha resposta também não verifica o tipo exato; aceita subclasse semelhante a esta resposta. Eu atualizei minha resposta para resolvê-la; desculpe por não ter notado essa parte em questão. Eu acho que a igualdade exata não está incluída na maioria das bibliotecas de asserções porque não é usada com frequência.
Franklin Yu
@Carmageddon A resposta de Franlin Yu funciona bem se você usar a importação de asserção hamcrest: `` `import static org.hamcrest.CoreMatchers.instanceOf; `` ss por suas amostras de código. Admito que tenha ignorado a resposta de Franklin e, de fato, essas duas respostas são funcionalmente equivalentes, então acho que é apenas uma questão de preferência no final.
kekko12
21

Solução para JUnit 5

A documentação diz:

No entanto, a org.junit.jupiter.Assertionsclasse de JUnit Jupiter não fornece um assertThat()método como o encontrado na org.junit.Assertclasse de JUnit 4 que aceita um Hamcrest Matcher. Em vez disso, os desenvolvedores são incentivados a usar o suporte interno para correspondentes fornecido por bibliotecas de asserções de terceiros.

Exemplo para 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));
    }

}

Exemplo para 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);
    }

}

Observe que isso pressupõe que você deseja testar comportamentos semelhantes a instanceof(que aceita subclasses). Se você deseja exatamente o mesmo tipo, não vejo uma maneira melhor do que afirmar que as duas classes são iguais, como você mencionou na pergunta.

Franklin Yu
fonte
1
Em certo sentido, o original assertThat()é adiado para Hamcrest, para que o JUnit também trabalhe com bibliotecas de afirmação de terceiros.
Franklin Yu
Acabei de testar esta resposta, NÃO está correta e gera vários erros de compilação: Início de expressão ilegal, início de tipo ilegal, ';' esperado ... Em outras palavras, seu segundo parâmetro para o correspondente assertThat NÃO PODE ser "instanceof (BaseClass.class)"! Na verdade, você nem digitou isso corretamente, a sintaxe que você usou é um pouco diferente - "InstanceOf (" - como uma chamada de função! Na verdade, não existe essa função ... ela foi testada por alguém? Parece que foi manualmente) digitado sem testes
Carmageddon
@Carmageddon Forneci duas respostas, uma para Hamcrest e a outra para AssertJ. De qual você está falando?
Franklin Yu
@ Carmageddon Suspeito que você esteja falando do exemplo do Hamcrest e que tenha digitado errado instanceOfcomo instanceof(lembre-se do caso). instanceOfé uma função enquanto instanceofé uma palavra-chave Java .
Franklin Yu
Referi-me ao que Hamcrest é claro, e eu tentei tanto palavra-chave e como uma função depois que eu notei isso é como você o escreveu - não existe tal função ...
Carmageddon
3

Solução para JUnit 5 para Kotlin!

Exemplo para 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))
    }

}

Exemplo para 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)
    }

}
Naruto Sempai
fonte
1
Obrigado por esta solução assertJ muito elegante
Aleks Nine