java.lang.IllegalStateException:前面的方法调用getMessage(“title”)缺少行为定义

时间:2010-06-09 08:34:09

标签: java unit-testing testng easymock

我正在使用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对象创建)。

任何人都可以帮助我在这种情况下测试。

感谢。

5 个答案:

答案 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