Test driven development (TDD) is a critical component of software development. If a component is not well tested, its said to be broken. Suppose you are writing the temperature conversion component and you would like to make sure it works on all scenarios before handing it over to QA team. What and how do we do making sure at least from development perspective things are not broken and developers have pretty good confidence on what they are delivering. Here are the things developers prefer to do in order to avoid the issues which come late in the product life cycle (PDLC):
* test component locally and manually
* test with load of the data and making sure tests pass with the data set
* write junit which gets tested when the code is build
The first two steps are developer driven which is hard to replay every time there is a new release of upgrade of the software. The last option (junit) is basically used to automate what developer has tested manually.
You could find a lots of junit tutorials on line on how to write the junit test cases. Junits help you test your code however sometimes there are some components hidden deep inside the code hierarchy which becomes hard to simulate. Then how do we fake those hidden components/methods/APIs to behave on a given inputs and provide expected results?
The answer is mock-objects. How mock-objects replay/proxy the hidden objects and behave as per your requirements? There's deep, dark magic here, coming from a combination of Java 5 generics and dynamic proxies introduced way back in Java 1.3. Fortunately, you don't need to understand how it works in order to use it.
mock-object?: Mocking allows you to test a class or method in isolation. In other words: “A mock object is a dummy interface or class in which you define the dummy output of a certain method call.”
How EasyMock works?
* create a mock object
it is used to create the mock object of the class interface we are trying to create poxy and simulate.
MyInterface mock = createMock ( MyInterface.class );
* record behavior of the mock object
training the mock by making expected method calls on it.
expect( mock.doStuff( "argument" )).andReturn( "returnValue" );
* replay the behavior
it tells EasyMock framework to stop recording the behavior and gets ready to return data as per expectation when it gets called.
replay( mock );
* executing the user code which we need to test (this codebase calls the method which is mocked)
AssertEquals(5, test.perform()); //assume perform() method calls doStuff() method.
* verify the behavior
method checks to see if the mock actually received all the calls you expect. The method is used to make sure that all of the behavior expected from the collaborators is valid.
verify(mock);
Its so easy as that. to get more details on downloading the jar files for easymock, check easymock.org site. Here is the snippet of the pom.xml file which is used to introduce dependency on easymock library so that the code once build could utilize the framework.
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymockclassextension</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
Have a closer look at above pom artifacts and you will notice that we have included ‘easymockclassextensio’ library. What it is used for? It is used in some advanced testing scenarios e.g.
Sometimes you may need to mock only some methods of a class and keep the normal behavior of others. This usually happens when you want to test a method that calls some others in the same class. So you want to keep the normal behavior of the tested method and mock the others.
ToMock mock = createMock(ToMock.class, new Method[] { ToMock.class.getMethod("mockedMethod", null) } );
Additional use cases:
To Throw An Exception
expect(mock.method()).andThrow(expectedException);
Expecting A Method With void Return Type
mock.clear();
ExpectLastCall();
Need to mention no. Of calls
expectLastCall().times(3);
Types of EasyMock:
Normal — createMock(): All of the expected methods must be called with the specified arguments regardless of the order. Calls to unexpected methods cause the test to fail.
Strict — createStrictMock(): All expected methods must be called with the expected arguments, in a specified order. Calls to unexpected methods cause the test to fail.
Nice — createNiceMock(): All expected methods must be called with the specified arguments in any order. Calls to unexpected methods do not cause the test to fail.
How to do repeated calls to methods?
By default mock expects minimum 1 call.
* times(int min, int max) : to expect between min and max calls,
* AtLeastOnce() : to expect at least one call, and
* AnyTimes() : to expected an unrestricted number of calls.
References:
EasyMock: http://www.easymock.org
easymockclassextension: http://easymock.org/EasyMock2_0_ClassExtension_Documentation.html
Introduction to TDD: http://www.agiledata.org/essays/tdd.html