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

java.lang.IllegalStateException:前面的方法调用getMessage(“title”)缺少行为定义,java,unit-testing,testng,easymock,Java,Unit Testing,Testng,Easymock,我正在使用EasyMock(版本2.4)和TestNG编写UnitTest 我有以下一个场景,我无法更改类层次结构的定义方式 我正在测试ClassB,它扩展了ClassA ClassB看起来像这样 public class ClassB extends ClassA { public ClassB() { super("title"); } @Override public String getDisplayName() {

我正在使用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");
    }

}
A类代码

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

    }
}
public class MessageResourse {
    public String getMessage(String code) 
    {
        return code;
    }
}
客户端消息类代码

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

    }
}
public class MessageResourse {
    public String getMessage(String code) 
    {
        return code;
    }
}
消息资源类代码

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

    }
}
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”)缺少行为定义

在调试时,我发现它没有考虑mock方法调用 mockMessageResources.getMessage(“ClassB.title”)它是从构造函数(ClassB对象创建)调用的

有谁能帮我在这种情况下如何测试吗


谢谢。

在调用测试中的方法之前,您需要调用
EasyMock.replay(mock)
。调用测试中的方法后,可以调用
EasyMock.verify(mock)
来验证是否调用了mock

接下来,您需要添加另一个带有“title”参数的
expect
调用,因为您调用了它两次

代码:


在我的例子中,这是由于省略了返回值规范(andReturn(…)造成的。
有关更多详细信息。

这可能有多种原因(
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);
}
@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());
}
这将在带有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
}

您应该在
expect
调用之后和使用模拟之前,将调用放到
replay
。在这种情况下,您应该将测试更改为以下内容:

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

对我来说,发生这种异常是因为我尝试存根的方法是
final
(我没有意识到)


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

这里也一样。检查方法是否在您不期望的情况下返回某些内容(方法链接)似乎是个好主意。缺少
reset()
是我的问题。