我正在使用EasyMock(版本2.4)和TestNG来编写UnitTest。
我有以下场景,我无法改变定义类层次结构的方式。
我正在测试扩展ClassA的ClassB。
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;
}
}
测试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”) ,因为它是从construtor调用的(ClassB对象创建)。
任何人都可以帮助我在这种情况下测试。
感谢。
答案 0 :(得分:40)
在调用测试方法之前,您需要调用EasyMock.replay(mock)
。在调用测试方法后,您可以调用EasyMock.verify(mock)
来验证模拟被调用。
接下来,您需要使用“title”参数添加另一个expect
调用,因为您调用它两次。
代码:
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);
答案 1 :(得分:20)
在我的情况下,它是由于省略了返回值规范(andReturn(...))。 http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html了解更多详情。
答案 2 :(得分:0)
这可能有多种原因(someMock
是此答案中模拟对象的名称)。
一方面,您可能需要通过
expect(someMock.someMethod(anyObject()).andReturn("some-object");
就像Reda's answer一样。
您也可能忘记在使用模拟之前致电replay(someMock)
,就像您在Julien Rentrop's answer中看到的那样。
这里没有提到的最后一件事是你在测试之前在其他地方使用了模拟,忘了通过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
}
答案 3 :(得分:0)
您应该在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());
}
答案 4 :(得分:0)
对我来说,发生此异常是因为我尝试存根的方法是final
(我还没有意识到)。
如果您想存根final
方法,则需要使用Powermock。