web-dev-qa-db-fra.com

EasyMock 3.0, la classe moqueuse lève Java.lang.IllegalStateException: pas de dernier appel sur une maquette disponible

L'exécution du test unitaire suivant lève l'exception: Java.lang.IllegalStateException: pas de dernier appel sur une maquette disponible


import org.easymock.*;
import org.junit.*;

public class MyTest {

    @Test
    public void testWithClass() {
        Thread threadMock = EasyMock.createMock(Thread.class);
        EasyMock.expect(threadMock.isAlive()).andReturn(true);
    }
}

Je ne suis pas sûr de ce que je fais mal et je ne trouve aucun bon exemple sur le Web. Comment se moquer d'une classe en utilisant EasyMock 3.0. Quel est le problème avec le test unitaire ci-dessus? Toute aide serait grandement appréciée.

Mon projet inclut les dépendances maven suivantes

<dependency>
   <groupId>org.easymock</groupId>
   <artifactId>easymock</artifactId>
   <version>3.0</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib-nodep</artifactId>
   <version>2.2</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.objenesis</groupId>
   <artifactId>objenesis</artifactId>
   <version>1.2</version>
   <scope>test</scope>
</dependency>
22
Nathan Reese

La raison de cette exception est que Thread#isAlive() est une méthode final, mais EasyMock ne prend pas en charge la simulation des méthodes finales. Ainsi, l'appel à cette méthode qui apparaît à l'intérieur de EasyMock.expect(...) n'est pas considéré comme un "appel sur une maquette".

Pour se moquer des méthodes finales, vous auriez besoin d'un outil de simulation différent, tel que JMockit (que je développe):

public void testMockingFinalMethod(@Mocked("isAlive") Thread mock)
{
    new Expectations()
    {{
        mock.isAlive(); result = true;
    }};

    assertTrue(mock.isAlive());
}

L'API mocking ne nécessite pas réellement que les méthodes à mocker soient spécifiées explicitement, dans le cas général. Cependant, la classe Thread est délicate.

19
Rogério

Votre méthode de test semble correcte, sauf que vous n'avez pas préparé l'objet fantaisie que vous avez créé. Cela doit être fait en utilisant

EasyMock.replay(mockObject1, mockObject2, ...);

Cela préparera l'objet simulé afin qu'il soit celui qui sera utilisé lors de l'exécution de votre JUnit. Aucun problème avec vos dépendances également.

De plus, vous ne semblez pas appeler la méthode réelle que vous testez ici. Habituellement, la façon d'écrire une méthode de test serait d'écrire une méthode JUnit, en utilisant des bibliothèques de simulation (comme EasyMock et PowerMock) UNIQUEMENT lorsqu'il y a des objets externes au-delà du contexte de la méthode de test, puis en rejouant tous les objets simulés (ce qui prépare la pour se substituer aux objets métier réels dans le test). Après cela, vous appelez la méthode réelle que vous essayez de tester et validez la fonctionnalité à l'aide des méthodes org.junit.Assert.assertXXX().

11
Nagendra U M

J'ai eu plusieurs appels à EasyMock.replay(mock) dans un scénario de test ou suite à l'origine de ce problème, et l'appel de EasyMock.reset(mock) entre chacun a résolu le problème.

0
SlappyTheFish