web-dev-qa-db-fra.com

java.lang.IllegalStateException: définition du comportement manquante pour l'appel de méthode précédent getMessage ("title")

J'utilise EasyMock (version 2.4) et TestNG pour écrire UnitTest.

J'ai un scénario suivant et je ne peux pas changer la façon dont la hiérarchie de classe est définie.

Je teste ClassB qui étend ClassA.

ClassB ressemble à ceci

public class ClassB extends ClassA  {

  public ClassB()
    {
        super("title");
    }

    @Override
    public String getDisplayName() 
    {
        return ClientMessages.getMessages("ClassB.title");
    }

}

Code de classe

public abstract class ClassA {
    private String title;

    public ClassA(String title)
    {
        this.title = ClientMessages.getMessages(title);
    }

    public String getDisplayName()
    {
        return this.title;
    }
}

Code de la classe ClientMessages

public class ClientMessages {
    private static MessageResourse messageResourse;

    public ClientMessages(MessageResourse messageResourse) 
    {
        this.messageResourse = messageResourse;
    }
    public static String getMessages(String code) 
    {
        return messageResourse.getMessage(code);

    }
}

Code de la classe MessageResourse

public class MessageResourse {
    public String getMessage(String code) 
    {
        return code;
    }
}

Test de la classe B

import static org.easymock.classextension.EasyMock.createMock;

import org.easymock.classextension.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;

public class ClassBTest
{
    private MessageResourse mockMessageResourse = createMock(MessageResourse.class);
    private ClassB classToTest;
    private ClientMessages clientMessages;


    @Test
    public void testGetDisplayName()
    {

    EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");

        clientMessages = new ClientMessages(mockMessageResourse);

        classToTest = new ClassB();

        Assert.assertEquals("someTitle" , classToTest.getDisplayName());
        EasyMock.replay(mockMessageResourse);
    }
}

Lorsque j'exécute ce test, je reçois l'exception suivante:

Java.lang.IllegalStateException: définition du comportement manquante pour l'appel de méthode précédent getMessage ("title")} _

Lors du débogage, ce que j’ai trouvé est qu’il n’envisage pas l’appel de méthode fictive mockMessageResourse.getMessage ("ClassB.title")} [ tel qu’il a été appelé depuis le constructeur (création d’objets ClassB) .

Quelqu'un peut-il m'aider s'il vous plaît comment tester dans ce cas.

Merci.

25
user362199

Vous devez appeler EasyMock.replay(mock) avant d'appeler la méthode testée. Après avoir appelé la méthode testée, vous pouvez appeler EasyMock.verify(mock) pour vérifier que la maquette est appelée.

Ensuite, vous devez ajouter un autre appel expect avec l’argument "title" puisque vous l’appelez deux fois. 

Code:

EasyMock.expect(mockMessageResourse.getMessage("title")).andReturn("title");    
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);

classToTest = new ClassB();

Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.verify(mockMessageResourse);
40
Julien Rentrop

Dans mon cas, cela était dû à l'omission d'une spécification de valeur de retour (andReturn (...)) . http://www.smcmaster.com/2011/04/easymock-issue-1-missing -behavior.html pour plus de détails.

20
Reda

Vous devez passer votre appel à replay après les appels expect et avant vous utilisez votre maquette. Dans ce cas, vous devriez changer votre test en quelque chose comme ceci:

@Test
public void testGetDisplayName()
{ 

    EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
    EasyMock.replay(mockMessageResourse);

    clientMessages = new ClientMessages(mockMessageResourse);

    classToTest = new ClassB();

    Assert.assertEquals("someTitle" , classToTest.getDisplayName());
}
0
Mahdi

Cela peut avoir différentes causes (someMock est le nom de votre objet fictif dans cette réponse) . D'un côté, il se peut que vous deviez attendre l'appel via

expect(someMock.someMethod(anyObject()).andReturn("some-object");

comme dans La réponse de Reda . Il se peut également que vous ayez oublié d'appeler replay(someMock) avant d'utiliser la maquette, comme vous pouvez le voir dans la réponse de Julien Rentrop

Une dernière chose possible qui n’a pas été mentionnée ici est que vous avez utilisé la maquette quelque part avant dans un test et que vous avez oublié de réinitialiser la maquette via reset(someMock).

Cela peut arriver si vous avez plusieurs tests unitaires comme celui-ci:

private Object a = EasyMock.createMock(Object.class);

@Test
public void testA() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

@Test
public void testB() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

Cela échouera sur un test avec IllegalStateException, car le faux a n'a pas été réinitialisé avant d'être utilisé lors du prochain test. Pour le résoudre, vous pouvez procéder comme suit:

private Object a = EasyMock.createMock(Object.class);

@Test
public void testA() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

@Test
public void testB() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

@After
public void tearDown() throws Exception {
   reset(a); // reset the mock after each test
}
0
lukaswelte