EasyMock 3.0,模拟类抛出java.lang.IllegalStateException:没有最后一次调用可用的模拟

时间:2010-08-16 16:02:26

标签: easymock

运行以下单元测试会抛出异常:java.lang.IllegalStateException:没有最后一次调用可用的模拟


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

我不确定我做错了什么,在网上找不到任何好的例子。你如何使用EasyMock 3.0模拟一个类。上述单元测试有什么问题?任何帮助将不胜感激。

我的项目包含以下maven依赖项

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

3 个答案:

答案 0 :(得分:19)

此异常的原因是Thread#isAlive()final方法,但EasyMock不支持模拟最终方法。因此,EasyMock.expect(...)中出现的对此方法的调用不会被视为“模拟调用”。

要模拟最终方法,您需要一个不同的模拟工具,例如JMockit(我开发):

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

    assertTrue(mock.isAlive());
}

在一般情况下,模拟API实际上并不要求显式指定要模拟的方法。但是,Thread类是一个棘手的类。

答案 1 :(得分:10)

您的测试方法看起来很好,但您没有 准备 您创建的模拟对象。这必须使用

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

这将准备模拟对象,使其成为运行JUnit时使用的对象。您的依赖项也没有问题。

此外,您似乎没有调用实际方法,您在此处进行单元测试。通常,编写测试方法的方法是使用模拟库编写JUnit方法 (例如EasyMock和PowerMock)仅当有超出测试方法上下文的外部对象时,然后重放所有模拟对象(它们准备模拟以替换测试中的真实业务对象)。之后,您调用要测试的实际方法,并使用org.junit.Assert.assertXXX()方法验证功能。

答案 2 :(得分:0)

我在一个测试用例或套件中多次调用EasyMock.replay(mock)导致了此问题,并且在每个测试用例或套件中调用EasyMock.reset(mock)解决了该问题。