运行以下单元测试会抛出异常: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>
答案 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)
解决了该问题。