Java.lang.IllegalStateException: 前面的方法调用getMessage("title")缺少行为定义。

37

我正在使用EasyMock(版本2.4)和TestNG编写单元测试。

我有一个如下的场景,我不能更改类层次结构的定义。

我正在测试继承自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;
    }
}

客户端消息类代码

public class ClientMessages {
    private static MessageResourse messageResourse;

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

    }
}

MessageResource类代码

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对象)中调用的。

请问有谁能帮助我如何在这种情况下进行测试。

谢谢。

5个回答

49

在调用被测试的方法之前,您需要调用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);

24

2
同样的想法。检查方法是否返回了一些东西,即使你不希望它(方法链接),似乎是一个好主意。 - Pieter De Bie

3

这可能有多种原因(someMock是本答案中模拟对象的名称)。一方面,可能需要通过以下方式来期望调用:

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

就像Reda的回答中所说的那样。 也可能是您在使用模拟对象之前忘记调用replay(someMock),就像您在Julien Rentrop的回答中看到的那样。

最后一件可能没有提到的事情是,在测试中您在其他地方使用了模拟对象,并且忘记通过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而失败,因为mock 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
}

缺少 reset() 是我的问题。 - RamValli

1
你应该在expect调用之后,在使用模拟对象之前,调用replay。在这种情况下,你需要将测试更改为类似以下的内容:
@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

对我来说,这个异常是因为我试图存根的方法是final(这是我没有意识到的)。

如果你想要存根一个final方法,你需要使用Powermock


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接