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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3004184/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:30:12  来源:igfitidea点击:

java.lang.IllegalStateException: missing behavior definition for the preceding method call getMessage("title")

javaunit-testingtestngeasymock

提问by user362199

I'm using EasyMock(version 2.4) and TestNG for writing UnitTest.

我正在使用 EasyMock(2.4 版)和 TestNG 来编写 UnitTest。

I have a following scenario and I cannot change the way class hierarchy is defined.

我有以下场景,我无法更改定义类层次结构的方式。

I'm testing ClassB which is extending ClassA.

我正在测试扩展 ClassA 的 ClassB。

ClassB look like this

B类看起来像这样

public class ClassB extends ClassA  {

  public ClassB()
    {
        super("title");
    }

    @Override
    public String getDisplayName() 
    {
        return ClientMessages.getMessages("ClassB.title");
    }

}

ClassA code

A类代码

public abstract class ClassA {
    private String title;

    public ClassA(String title)
    {
        this.title = ClientMessages.getMessages(title);
    }

    public String getDisplayName()
    {
        return this.title;
    }
}

ClientMessages class code

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 Class code

消息资源类代码

public class MessageResourse {
    public String getMessage(String code) 
    {
        return code;
    }
}

Testing ClassB

测试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);
    }
}

When I'm running this this test I'm getting following exception:

当我运行此测试时,出现以下异常:

java.lang.IllegalStateException: missing behavior definition for the preceding method call getMessage("title")

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

While debugging what I found is, it's not considering the mock method call mockMessageResourse.getMessage("ClassB.title")as it has been called from the construtor (ClassB object creation).

在调试我发现的是,它没有考虑模拟方法调用 mockMessageResourse.getMessage("ClassB.title")因为它是从构造函数调用的(ClassB 对象创建)。

Can any one please help me how to test in this case.

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

Thanks.

谢谢。

回答by Julien Rentrop

You need to call EasyMock.replay(mock)before calling the method under test. After calling the method under test you can call EasyMock.verify(mock)to verify the mock is called.

您需要EasyMock.replay(mock)在调用被测方法之前调用。调用被测方法后,您可以调用EasyMock.verify(mock)以验证模拟是否被调用。

Next you need to add another expectcall with the "title" argument since you call it twice.

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

Code:

代码:

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

回答by Reda

In my case, it was caused by the omission of a return value specification (andReturn(...)). http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.htmlfor more details.

就我而言,这是由于省略了返回值规范(andReturn(...))造成的。 http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html了解更多详情。

回答by lukaswelte

This can have various causes (someMockis the name of your mocked Object in this answer). On the one side it can be that you need to expect the call via

这可能有多种原因(someMock是此答案中模拟对象的名称)。一方面,您可能需要通过以下方式期待呼叫

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

like in Reda's answer. It can also be that you forgot to call replay(someMock)before you used the mock, like you can see in Julien Rentrop's answer.

就像在Reda 的回答中一样。也可能是您replay(someMock)在使用模拟之前忘记打电话,就像您在Julien Rentrop 的回答中看到的那样。

A last thing that is possible that wasn't mentioned here is that you used the mock somewhere else before in a test and forgot to reset the mock via reset(someMock).

此处未提及的最后一件事是,您之前在测试中在其他地方使用了模拟,而忘记通过reset(someMock).

This can happen if you have multiple Unit Tests like this:

如果您有多个这样的单元测试,就会发生这种情况:

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

This will fail on one test with the IllegalStateException, because the mock a was not reset before being used in the next test. To solve it you can do the following:

这将在带有 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
}

回答by Mahdi

You should put your call to replayafter the expectcalls, and beforeyou use your mock. In this case you should change your test to something like this:

您应该在调用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());
}