EasyMock教程
EasyMock是基于Java的模拟框架,可与其他单元测试框架(例如JUnit和TestNG)结合使用。
EasyMock与Mockito模拟框架非常相似。
EasyMock允许我们创建接口和具体类的模拟对象并指定其行为。
然后,我们可以使用这些模拟程序编写代码来测试我们的主类。
这种方式简化了编写单元测试的过程,因为我们无需关心外部依赖项。
EasyMock
我们可以使用EasyMock创建模拟对象,然后将它们注入到我们要测试的类中。
但是,EasyMock也有某些限制。
EasyMock无法模拟最终方法和私有方法。
如果在模拟对象上调用了这些方法,则将调用普通方法。EasyMock为equals(),toString(),hashCode()和finalize()方法提供了内置行为。
这意味着我们无法记录这些方法的行为。
EasyMock Maven依赖关系
我们可以将以下依赖项添加到我们的maven项目中,以使用EasyMock模拟框架。
<dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.6</version> <scope>test</scope> </dependency>
EasyMock教程
让我们创建一些示例类和服务来进行模拟。
我们将使用JUnit 5编写测试用例,并使用EasyMock来创建模拟对象。
package com.theitroad.utils;
public interface Calculator {
int add(int x, int y);
int multiply(int x, int y);
}
package com.theitroad.utils;
public class MathUtils {
private Calculator calc;
public MathUtils(Calculator c) {
this.calc = c;
}
public int add(int i, int j) {
return this.calc.add(i, j);
}
public int multiply(int i, int j) {
return this.calc.multiply(i, j);
}
}
请注意,由于我们正在模拟测试用例,因此无需使用计算器实现即可编写测试用例。
这样,我们可以在我们的应用程序中应用测试驱动开发(TDD)模型。
org.easymock.EasyMock`类提供了大多数有用的方法。
由于它们大部分是静态的,因此我们可以将其导入以编写流利且更具可读性的代码。
我们还可以模拟一个具体的类并指定其行为。
我们首先来看一个简单的示例,在该示例中我们将模拟ArrayList类。
package com.theitroad.easymock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.mock;
import static org.easymock.EasyMock.replay;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import org.junit.jupiter.api.Test;
public class EasyMockMethodExample {
@Test
public void test() {
ArrayList<Integer> mockList = mock(ArrayList.class);
expect(mockList.add(10)).andReturn(true);
expect(mockList.add(20)).andReturn(true);
expect(mockList.size()).andReturn(2);
expect(mockList.get(0)).andReturn(10);
replay(mockList);
mockList.add(10);
mockList.add(20);
//below will throw exception because it's not mocked
//mockList.add(30);
assertTrue(mockList.get(0) == 10);
assertEquals(mockList.size(), 2);
}
}
从EasyMock示例上面要注意的一些重要点是:
第一步是使用EasyMock
mock()方法创建模拟对象。
这个方法是重载的,在这里我们可以指定我们想要的模拟对象是好还是严格。
我们还可以指定在记录异常时使用的名称。
我们将在以后的文章中研究不同的" MockType"示例。下一步是使用
expect()和andReturn()链语句对方法调用的行为和输出进行存根。最后,我们必须调用replay()方法来开始在模拟对象上使用存根方法。
如果我们调用一个未存根的方法,则将得到java.lang.AssertionError。
EasyMock注释– @ Mock,@ TestSubject
EasyMock还提供了一些注释来创建模拟对象。
@Mock:用于指定EasyMock模拟的字段。
@TestSubject与字段一起使用,以便EasyMock将在其字段上注入使用@Mock创建的模拟。
使用批注时,我们必须使用" EasyMockRunner"," EasyMockRule"或者" EasyMockSupport.injectMocks(Object)"来初始化和注入模拟对象。
由于我们使用的是JUnit-5,因此我们不能使用EasyMockRunner和EasyMockRule,因为它们尚未支持。
因此,我们将不得不使用EasyMockSupport.injectMocks(Object)。
我们可以在@ BeforeEach方法中调用此方法。
这是使用EasyMock注释模拟对象的完整示例。
package com.theitroad.easymock;
import static org.easymock.EasyMock.*;
import static org.junit.jupiter.api.Assertions.*;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.theitroad.utils.Calculator;
import com.theitroad.utils.MathUtils;
public class EasyMockAnnotationExample {
@Mock
private Calculator mockCalculator;
@TestSubject
private MathUtils mathUtils = new MathUtils(mockCalculator);
@BeforeEach
public void setup() {
EasyMockSupport.injectMocks(this);
}
@Test
public void test() {
expect(mockCalculator.add(1, 1)).andReturn(2);
expect(mockCalculator.multiply(10, 10)).andReturn(100);
replay(mockCalculator);
assertEquals(mathUtils.add(1, 1), 2);
assertEquals(mathUtils.multiply(10, 10), 100);
}
}
EasyMock迭代器样式存根
我们可以通过将它们与times()链接起来,为相同的方法调用指定不同的行为。
让我们看一个简单的例子来清楚地理解这一点。
//Iterator Style Mocking reset(mockList); expect(mockList.size()).andReturn(1).times(2) //return 1 for first 2 calls .andReturn(2).times(1) //return 2 for 3rd call .andReturn(4); //return 4 for 4th call replay(mockList); assertEquals(mockList.size(), 1); assertEquals(mockList.size(), 1); assertEquals(mockList.size(), 2); assertEquals(mockList.size(), 4);

