0% found this document useful (0 votes)
50 views45 pages

Easymock: Testing Mediator Objects

The document discusses how to test mediator objects that interact with other objects. It introduces mock objects as dummy dependencies that can be passed to the code under test. It then introduces the EasyMock framework, which makes it easier to create and work with mock objects by automating the setup of expectations and verification of interactions.

Uploaded by

Almog Goldberg
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
50 views45 pages

Easymock: Testing Mediator Objects

The document discusses how to test mediator objects that interact with other objects. It introduces mock objects as dummy dependencies that can be passed to the code under test. It then introduces the EasyMock framework, which makes it easier to create and work with mock objects by automating the setup of expectations and verification of interactions.

Uploaded by

Almog Goldberg
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

EasyMock

Testing Mediator Objects

copyright 2008 trainologic LTD


EasyMock

• Mediator Objects and Testing


• Introduction to Mock Objects
• Introduction to EasyMock
• Setting Expectations
• Mock Verification

copyright 2008 trainologic LTD


EasyMock

Testing Mediator Objects

• The JUnit testing framework, makes the testing of an


independent, non-void method, simple.
• But... how do we test an method with no return value?
• How do we test a method that interacts with other
domain objects?

3
copyright 2008 trainologic LTD
EasyMock

Testing Mediator Objects

• Let’s say we want to test a method that gets a


Collection and an Object, checks whether the Collection
contains the Object and only if it doesn’t, adds the
Object to the Collection.
• How would you implement this test?

4
copyright 2008 trainologic LTD
EasyMock

Testing Mediator Objects

• What if the method only gets a simple collection and


print it using a Logger?

5
copyright 2008 trainologic LTD
EasyMock

Testing Mediator Objects

• Many business objects that are really important to test


are mediators, i.e., they contain methods which
interact with other domain objects.

• Since in unit testing we want to test a unit without its


dependencies, we will have to eliminate them
somehow.
• We do this by passing dummy objects to “fill in” for the
real dependencies.

6
copyright 2008 trainologic LTD
EasyMock

Testing Mediator Objects

• These dummy objects are called Mock Objects.


• Which Mock Objects do we need for the add to
collection example?
• Which Mock Objects do we need for the print collection
example?

7
copyright 2008 trainologic LTD
EasyMock

• Mediator Objects and Testing


• Introduction to Mock Objects
• Introduction to EasyMock
• Setting Expectations
• Mock Verification

copyright 2008 trainologic LTD


EasyMock

Introduction to Mock Objects


• So... How “dumb” is a mock?
• First, it has to implement the same interface as the
original dependent object. Otherwise, the compiler
won’t let us pass it to the tested object.

• Second, it should supply the tested code with


everything it expects from the dependent object.

• Third, it should be able to check that the tested code is


using the dependent object (the Mock) correctly.

9
copyright 2008 trainologic LTD
EasyMock

Introduction to Mock Objects

• To use a Mock object we should:


• Create instance of the Mock.
• Set state and expectations.
• Invoke the tested code while passing the Mock as
parameter.
• Verify the Mock has been used correctly.

• Let’s see an example...

10
copyright 2008 trainologic LTD
EasyMock

Introduction to Mock Objects

• Let’s say we want to implement a special collection that


informs its listeners when and element is added to the
collection.

• That design is following the GoF Observer design


pattern.

11
copyright 2008 trainologic LTD
EasyMock

Introduction to Mock Objects

• To test this behavior we have to write the following


test:

@Test
public void testObservableCollection() {
Object objToAdd = new Object();
listenerMock.expect(1);
collection.addListener(listenerMock);
collection.add(objToAdd);
listenerMock.verify();
}

12
copyright 2008 trainologic LTD
EasyMock

Introduction to Mock Objects


• Let’s take a look at ListenerMock:

public class ListenerMock implements Listener {


private int counter;
private int expectedCounter;

public void elementAdded(){


counter++;
}

public void expect(int numOfCalls) {


expectedCounter = numOfCalls;
}
public void verify() {
if (counter != expectedCounter)
throw new AssertionFailedError();
}
}

13
copyright 2008 trainologic LTD
EasyMock

Introduction to Mock Objects

• As you can see, even though this is a very simple Mock,


it is cumbersome to write.

• It would have been much less pleasant if we had a


more complicated interface or if we had to check for
parameter values, return values and the order of
method calls.

14
copyright 2008 trainologic LTD
EasyMock

• Mediator Objects and Testing


• Introduction to Mock Objects
• Introduction to EasyMock
• Setting Expectations
• Mock Verification

copyright 2008 trainologic LTD


EasyMock

Introduction to EasyMock

• An open-source project providing an easy way to work


with Mock objects.

• Can be freely downloaded from easymock.org.


• Released under the MIT License.

16
copyright 2008 trainologic LTD
EasyMock

EasyMock - Benefits

• No need to write Mock objects by hand.


• Refactoring-safe, no need to refactor Mock in case the
interface has changed.
• Supports return values and Exceptions.
• Supports checking the order of calls for a single object
and for multiple projects.

• Uses a convenient record/replay mechanism.

17
copyright 2008 trainologic LTD
EasyMock

EasyMock - Installation

• Download EasyMock.
• Unzip the package.
• Add easymock.jar to your classpath.
• That is it!!!

18
copyright 2008 trainologic LTD
EasyMock

EasyMock

Create a Mock

19
copyright 2008 trainologic LTD
EasyMock

EasyMock

Create a Mock

Set Expectations

19
copyright 2008 trainologic LTD
EasyMock

EasyMock

Create a Mock

Set Expectations

Run Test

19
copyright 2008 trainologic LTD
EasyMock

EasyMock

Create a Mock

Set Expectations

Run Test

Verify

19
copyright 2008 trainologic LTD
EasyMock

EasyMock

• Let’s try to implement the same ListenerMock using


EasyMock.

@Test
public void testObservableCollection() {
mockListener = EasyMock.createMock(Listener.class);
//Recording
mockListener.elementAdded();
EasyMock.replay(mockListener);
//Playing
Object objToAdd = new Object();
collection.addListener(mockListener);
collection.add(objToAdd);
//Verifying
EasyMock.verify(mockListener);
}

20
copyright 2008 trainologic LTD
EasyMock

EasyMock

• No need to implement the Listener interface. The


implementation is being created by EasyMock on the
fly.

• After the creation of the Mock, EasyMock is in recording


mode.

• In the recording mode, we invoke methods of the Mock


and these method calls are recorded and used as
expectations.

21
copyright 2008 trainologic LTD
EasyMock

EasyMock

• The replay() method changes the mode from recording


to playing.

• Then the actual test is run and the Mock is being used
by the tested code.

• Finally, the verify() method makes sure the play was


identical to the recording.

22
copyright 2008 trainologic LTD
EasyMock

Creating Mock

• Creating a Mock is very easy... All we have to do is just


use the createMock() method and supply it with the
interface to implement.

Listener listenerMock = EasyMock.createMock(Listener.class);

23
copyright 2008 trainologic LTD
EasyMock

Creating Mock

• What happens if I don’t have an interface?


• Well... There are two options:
• Extract an interface;
• Use EasyMock Extension that works with classes as
well (separate download). The extension uses cglib to
dynamically create a sub-class.

• The next part of the chapter discus the expectation


settings and verification.

24
copyright 2008 trainologic LTD
EasyMock

• Mediator Objects and Testing


• Introduction to Mock Objects
• Introduction to EasyMock
• Setting Expectations
• Mock Verification

copyright 2008 trainologic LTD


EasyMock

Setting Expectations

• Setting expectations is mostly done by recording.


• But not everything can be recorded... A complementary
API enables us to refine our expectations.
• In the following example the Mock expects one call to
elementAdded() method.

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.elementAdded();
EasyMock.replay(listenerMock);

26
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Argument


Values
• In case there is a method argument, the Mock expects
an argument that equals() the argument in the
recording.

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.elementAdded(element);
EasyMock.replay(listenerMock);

27
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Number of


Calls
• If you want to expect more than one call, you can
either call the method several times in the recording
phase, or use the times() method.

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.elementAdded(element);
EasyMock.expectLastCall().times(3);
EasyMock.replay(listenerMock);

28
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Specifying


Return Values
• To specify what value is returned from a method call on
the Mock, use the expect(...).andReturn()

• During the playing phase, a call to getCallCount()


method will return 3.

listenerMock = EasyMock.createMock(Listener.class);
//Recording
EasyMock.expect(listenerMock.getCallCount()).andReturn(3);
EasyMock.replay(listenerMock);

29
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Specifying


Exception Throwing
• To specify that a method call on the Mock throws and
Exception, use the andThrow().

• During the playing phase, a call to getCallCount() will


throw a RuntimeException

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.getCallCount();
EasyMock.expectLastCall().andThrow(new RuntimeExcetion());
EasyMock.replay(listenerMock);

30
copyright 2008 trainologic LTD
EasyMock

Setting Expectations -
Combination
• We can combine all the options:

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.getCallCount();
EasyMock.expectLastCall()
.andReturn(3)
.times(2)
.andThrow(new RuntimeExcetion());
EasyMock.replay(listenerMock);

31
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Call Count

• By default, EasyMock fails if the count of the calls does


not match the exact number of call set in the recording.

• To change this behavior use times(), atLeastOnce() or


anyTimes()

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.getCallCount();
EasyMock.expectLastCall().times(2, 5); //At least 2 Max 5
EasyMock.expectLastCall().atLeastOnce(); //one or more
EasyMock.expectLastCall().anyTimes(); //zero or more
EasyMock.replay(listenerMock);

32
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Invocation


Order
• By default, EasyMock doesn’t check the order of
method calls.

• To change this behavior, you have to create a


StrictMock.

• We do that by calling the createStrictMock() method.


• StrictMocks check invocation orders on a single Mock.

listenerMock = EasyMock.createStrictMock(Listener.class);

33
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Invocation


Order
• If you want to verify invocation order that spans
several Mocks, you have to create a StrictControl and
use it to create the Mocks.

strictControl = EasyMock.createStrictControl();
listenerMock = strictControl.createMock(Listener.class);

34
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Argument


Matchers
• EasyMock expects arguments passed during the play
phase to be equals() to arguments being recorded.

• To have better control over argument values matching,


we use matchers.

• Matchers are simple methods that surround the


arguments during recording phase.

listenerMock = EasyMock.createMock(Listener.class);
//Recording
listenerMock.elementAdded(EasyMock.anyObject(element));
EasyMock.replay(listenerMock);

35
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Argument


Matchers
• There is a long list of available Matchers.
• All of them have self-descriptive names.
• In case you use matcher on one argument you must
use matchers on all arguments.

36
copyright 2008 trainologic LTD
EasyMock

Setting Expectations - Nice Mock

• If we have no expectations from the Mock and we only


want it to fill-in for the missing object and return
default values, we can create a “Nice Mock”.

• A nice Mock is a Mock which doesn’t care how we use


it.

• To create it, we simply call createNiceMock().

listenerMock = EasyMock.createNiceMock(Listener.class);

37
copyright 2008 trainologic LTD
EasyMock

• Mediator Objects and Testing


• Introduction to Mock Objects
• Introduction to EasyMock
• Setting Expectations
• Mock Verification

copyright 2008 trainologic LTD


EasyMock

Moving to Play Phase

• After setting all expectations, we change to play mode


and run our test code.

• Moving to play phase is done by calling the replay()


method and pass all Mocks as arguments.

EasyMock.replay(listenerMock);

39
copyright 2008 trainologic LTD
EasyMock

Moving to Play Phase

• During the play phase, EasyMock is tracking method


invocations on the Mocks.

• Even in case the invocations do not match the


expectations, EasyMock doesn’t fail the tests yet...

• There is still one more stage to go through...


Verification Stage.

40
copyright 2008 trainologic LTD
EasyMock

Verification

• After all test code finished executing, we want to check


that the Mock was used as we expected.

• To check this condition we simply call the verify()


method and pass all Mocks as arguments.

• In case one of our expectations is not fulfilled, an


exception is thrown and fails the test.

41
copyright 2008 trainologic LTD
EasyMock

Summary

• In order to unit-test isolated units we must use Mock


objects.

• Writing Mocks by hand is cumbersome.


• EasyMock is a simple and easy to use library that helps
us create Mock implementations on the fly.

• Expectation setting in EasyMock is done by applying


record/replay phases which provides great flexibility.

42
copyright 2008 trainologic LTD

You might also like