Nathan Reese
Nathan Reese

Reputation: 311

EasyMock 3.0, mocking class throws java.lang.IllegalStateException: no last call on a mock available

Running the following unit test throws the exception: java.lang.IllegalStateException: no last call on a mock available


import org.easymock.*;
import org.junit.*;

public class MyTest {

    @Test
    public void testWithClass() {
        Thread threadMock = EasyMock.createMock(Thread.class);
        EasyMock.expect(threadMock.isAlive()).andReturn(true);
    }
}

I am not sure what I am doing wrong and can not find any good examples on the web. How do you mock a class using EasyMock 3.0. What is wrong with the above unit test? Any help would be greatly appreciated.

My project includes the following maven dependencies

<dependency>
   <groupId>org.easymock</groupId>
   <artifactId>easymock</artifactId>
   <version>3.0</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib-nodep</artifactId>
   <version>2.2</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.objenesis</groupId>
   <artifactId>objenesis</artifactId>
   <version>1.2</version>
   <scope>test</scope>
</dependency>

Upvotes: 23

Views: 58427

Answers (3)

SlappyTheFish
SlappyTheFish

Reputation: 2384

I had multiple calls to EasyMock.replay(mock) within one test case or suite causing this issue, and calling EasyMock.reset(mock) between each solved the problem.

Upvotes: 0

Nagendra U M
Nagendra U M

Reputation: 621

Your test method looks fine, except that you have not prepared the mock object you have created. This has to be done using

EasyMock.replay(mockObject1, mockObject2, ...);

This will prepare the mocked object so that it is the one which will be used on running your JUnit. No issues with your dependencies as well.

Also, you don't seem to be calling the actual method which you are unit-testing here. Usually, the way to write a test method would be to write a JUnit method, using mocking libs (such as EasyMock and PowerMock) ONLY when there are external objects beyond the test method context, and then replaying all the mocked objects (which prepares the mocks to substitute for the real business objects in the test). After that, you call the actual method you are trying to test, and validate the functionality using org.junit.Assert.assertXXX() methods.

Upvotes: 11

Rog&#233;rio
Rog&#233;rio

Reputation: 16380

The reason for this exception is that Thread#isAlive() is a final method, but EasyMock does not support the mocking of final methods. So, the call to this method which appears inside EasyMock.expect(...) is not seen as a "call on a mock".

To mock final methods you would need a different mocking tool, such as JMockit (which I develop):

public void testMockingFinalMethod(@Mocked("isAlive") Thread mock)
{
    new Expectations()
    {{
        mock.isAlive(); result = true;
    }};

    assertTrue(mock.isAlive());
}

The mocking API doesn't actually require that methods to be mocked are specified explicitly, in the general case. The Thread class is a tricky one, though.

Upvotes: 19

Related Questions