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

74,103

Solution 1

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.

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

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

Solution 2

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.html for more details.

Solution 3

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

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.

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

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:

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
}

Solution 4

You should put your call to replay after the expect calls, and before you use your mock. In this case you should change your test to something like this:

@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());
}
Share:
74,103
Admin
Author by

Admin

Updated on September 17, 2020

Comments

  • Admin
    Admin over 3 years

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

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

    I'm testing ClassB which is extending ClassA.

    ClassB look like this

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

    ClassA code

    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

    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

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

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

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

    Thanks.

  • Pieter De Bie
    Pieter De Bie almost 9 years
    Same here. Checking if methods return something even when you don't expect it (method chaining) seems a good idea.
  • RamValli
    RamValli about 4 years
    missing reset() was my problem.