EasyMock is a java based mocking framework, which is used in conjunction with other unit testing frameworks such as JUnit and TestNG. EasyMock is very similar to Mockito mocking framework.
EasyMock allows us to create mock objects of interfaces and concrete classes and specify their behaviors. Then we can use these mocks to write code to test our main classes. This way writing unit tests are simplified as we don’t need to care about external dependencies.
EasyMock
We can use EasyMock to create mock objects and then inject them into the classes we want to test. However, EasyMock has certain limitations too.
- EasyMock can’t mock final and private methods. If these methods are called on mock object, then normal methods will get called.
- EasyMock provides built-in behavior for equals(), toString(), hashCode() and finalize() methods. It means that we can’t record our own behavior for these methods.
EasyMock Maven Dependencies
We can add the following dependencies to our maven project to use the EasyMock mocking framework.
1 2 3 4 5 6 7 8 |
<dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.6</version> <scope>test</scope> </dependency> |
EasyMock Tutorial
Let’s create some sample classes and services for mocking. We will use JUnit 5 for writing test cases along with EasyMock for creating mock objects.
1 2 3 4 5 6 7 |
package com.journaldev.utils; public interface Calculator { int add(int x, int y); int multiply(int x, int y); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.journaldev.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); } } |
Note that we don’t need to have Calculator implementation for writing our test cases because we are mocking them. This way we can apply the Test-Driven-Development (TDD) model in our application.
Most of the useful methods are provided in the org.easymock.EasyMock
class. Since they are mostly static, we can import them to write fluent and more readable code.
We can also mock a concrete class and specify its behaviors. Let’s first look at a simple example, where we will mock ArrayList class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.journaldev.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); } } |
Some important points to note from above EasyMock example are:
- First step is to create mock object using EasyMock
mock()
method. This method is overloaded where we can specify if we want our mock object to be nice or strict. We can also specify name to be used incase of logging exceptions. We will look into differentMockType
examples in future posts. - Next step is to stub the behavior and output of a method call using
expect()
andandReturn()
chain statements. - Finally, we have to call
replay()
method to start using stub methods on mock objects. - If we call a method that is not stubbed, we will get
java.lang.AssertionError
.
EasyMock Annotations – @Mock, @TestSubject
EasyMock also provides few annotations to create mock objects.
@Mock
: Used to specify a field to be mocked by EasyMock.@TestSubject
: Used with a field so that EasyMock will inject mocks created with @Mock on its fields.
When using annotations, we have to use EasyMockRunner
, EasyMockRule
or EasyMockSupport.injectMocks(Object)
to initialize and inject mock objects. Since we are using JUnit-5, we can’t use EasyMockRunner and EasyMockRule as they are not supported yet. So we will have to use EasyMockSupport.injectMocks(Object)
. We can call this method in @BeforeEach
method.
Here is the complete example of mocking objects using EasyMock annotations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com.journaldev.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.journaldev.utils.Calculator; import com.journaldev.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 Iterator Style Stubbing
We can specify different behaviors for the same method calls by chaining them with times()
. Let’s look at a simple example to understand this clearly.
1 2 3 4 5 6 7 8 9 10 11 12 |
//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); |
Summary
EasyMock is a simple tool to create mock objects and write unit tests easily. It’s very similar to Mockito and provides almost the same features as Mockito.
Reference: Official User Guide