23

运行以下单元测试会引发异常: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);
    }
}

我不确定我做错了什么,并且在网上找不到任何好的例子。你如何使用 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>
4

3 回答 3

19

这个异常的原因是那Thread#isAlive()是一个final方法,但是EasyMock不支持对final方法的mock。因此,对出现在内部的此方法的调用EasyMock.expect(...)不被视为“模拟调用”。

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

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

    assertTrue(mock.isAlive());
}

在一般情况下,模拟 API 实际上并不要求明确指定要模拟的方法。不过,这Thread门课很棘手。

于 2011-02-15T11:57:23.013 回答
11

您的测试方法看起来不错,只是您还没有准备好您创建的模拟对象。这必须使用

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

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

此外,您似乎没有在这里调用您正在单元测试的实际方法。通常,编写测试方法的方法是编写一个 JUnit 方法,仅在测试方法上下文之外有外部对象时使用模拟库(例如 EasyMock 和 PowerMock),然后重放所有模拟对象(这为模拟来替代测试中的真实业务对象)。之后,您调用您尝试测试的实际方法,并使用org.junit.Assert.assertXXX()方法验证功能。

于 2010-09-02T15:28:13.797 回答
0

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

于 2020-01-03T14:16:28.673 回答