Java.lang.IllegalStateException: определение отсутствующего поведения для предыдущего вызова метода getMessage ( "title" )
Я использую EasyMock (версия 2.4) и TestNG для написания UnitTest.
У меня есть следующий сценарий, и я не могу изменить способ определения иерархии классов.
Я тестирую ClassB, который расширяет ClassA.
КлассB выглядит так
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;
}
}
Тестирование ClassB
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" ), поскольку он был вызван из конструктора (создание объекта ClassB).
Может ли кто-нибудь помочь мне в этом случае проверить.
Спасибо.
Ответы
Ответ 1
Вам нужно позвонить EasyMock.replay(mock)
перед вызовом тестируемого метода. После вызова тестируемого метода вы можете вызвать EasyMock.verify(mock)
, чтобы проверить, что 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);
Ответ 2
В моем случае это было вызвано отсутствием спецификации возвращаемого значения (andReturn (...)).
http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html для более подробной информации.
Ответ 3
Это может иметь различные причины (someMock
- это имя вашего издевающегося объекта в этом ответе).
С одной стороны, может случиться так, что вам нужно ожидать вызова через
expect(someMock.someMethod(anyObject()).andReturn("some-object");
как в Reda answer.
Также может быть, что вы забыли называть replay(someMock)
, прежде чем использовать макет, как вы можете видеть в сообщении Julien Rentrop.
Последнее, что возможно, что здесь не упоминалось, заключается в том, что вы использовали макет где-то еще раньше в тесте и забыли reset mock через reset(someMock)
.
Это может произойти, если у вас есть несколько тестов Unit, таких как:
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 не был reset перед тем, как его использовать в следующем тесте. Чтобы решить эту проблему, вы можете сделать следующее:
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
}