java.lang.IllegalStateException: отсутствует определение поведения для предыдущего вызова метода getMessage ("title") - PullRequest
25 голосов
/ 09 июня 2010

Я использую EasyMock (версия 2.4) и TestNG для написания UnitTest.

У меня есть следующий сценарий, и я не могу изменить способ определения иерархии классов.

Я тестируюClassB, расширяющий ClassA.

ClassB выглядит следующим образом

public class ClassB extends ClassA  {

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

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

}

Код ClassA

public abstract class ClassA {
    private String title;

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

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

Код класса 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);

    }
}

Код класса MessageResourse

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

Класс тестирования 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);
    }
}

Когда я запускаю этот тест, я получаю следующее исключение:

java.lang.IllegalStateException: отсутствует определение поведения для предыдущего вызова метода getMessage ("title")

Во время отладки я обнаружил, что не учитывает вызов имитационного метода mockMessageResourse.getMessage ("ClassB.title") , как это былоВызван от construtor (создание объекта ClassB).

Может ли кто-нибудь помочь мне, как проверить в этом случае.

Спасибо.

Ответы [ 4 ]

40 голосов
/ 09 июня 2010

Вам необходимо вызвать EasyMock.replay(mock) перед вызовом тестируемого метода.После вызова тестируемого метода вы можете вызвать EasyMock.verify(mock), чтобы убедиться, что макет вызывается.

Затем вам нужно добавить еще один вызов expect с аргументом "title", так как вы вызываете его дважды.

Код:

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);
20 голосов
/ 29 апреля 2013

В моем случае это было вызвано пропуском спецификации возвращаемого значения (andReturn (...)). http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html для более подробной информации.

0 голосов
/ 14 мая 2018

Вы должны поставить свой вызов на replay после expect вызовов и на до , когда вы используете свой макет.В этом случае вы должны изменить свой тест на что-то вроде этого:

@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 голосов
/ 27 июля 2017

У этого могут быть разные причины (someMock - это название вашего осмеянного объекта в этом ответе). С одной стороны это может быть то, что вам нужно ожидать звонка через

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

как в Ответ Реды . Также может быть, что вы забыли позвонить replay(someMock), прежде чем использовать макет, как вы можете видеть в ответе Жюльена Рентропа .

Последнее, что возможно, что здесь не упоминалось, это то, что вы использовали макет где-то еще ранее в тесте и забыли сбросить макет через reset(someMock).

Это может произойти, если у вас есть несколько юнит-тестов, подобных этому:

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

Это приведет к сбою в одном тесте с IllegalStateException, поскольку макет a не был сброшен перед использованием в следующем тесте. Для ее решения вы можете сделать следующее:

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
}
...