EasyMock教程

时间:2020-02-23 14:41:19  来源:igfitidea点击:

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示例上面要注意的一些重要点是:

  • 第一步是使用EasyMockmock()方法创建模拟对象。
    这个方法是重载的,在这里我们可以指定我们想要的模拟对象是好还是严格。
    我们还可以指定在记录异常时使用的名称。
    我们将在以后的文章中研究不同的" 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);