1183 lines
46 KiB
HTML
1183 lines
46 KiB
HTML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
|
<title>EasyMock 3.1 Readme</title>
|
|
<link rel="stylesheet" href="easymock.css" />
|
|
</head>
|
|
<body><div class="bodywidth">
|
|
|
|
<h2>EasyMock 3.1 Readme</h2>
|
|
|
|
<p>Documentation for release 3.1 (2011-11-10)<br />
|
|
© 2001-2011 <a href="http://www.offis.de">OFFIS</a>, <a href="http://tammofreese.de">Tammo Freese</a>, <a href="http://www.ossia-conseil.com/blog/henri/">Henri Tremblay</a>.
|
|
</p>
|
|
<p>
|
|
EasyMock is a library that provides an easy way to use Mock Objects for given
|
|
interfaces or classes. EasyMock is available under the terms of the <a href="http://www.apache.org/licenses/LICENSE-2.0.txt">Apache 2 license</a>.
|
|
</p>
|
|
<p>
|
|
Mock Objects simulate parts of the behavior of domain code,
|
|
and are able to check whether they are used as defined.
|
|
Domain classes can be tested in isolation
|
|
by simulating their collaborators with Mock Objects.
|
|
</p>
|
|
<p>
|
|
Writing and maintaining Mock Objects often is a tedious
|
|
task that may introduce errors. EasyMock generates Mock Objects
|
|
dynamically - no need to write them, and no generated code!
|
|
</p>
|
|
<h2>
|
|
EasyMock Benefits
|
|
</h2>
|
|
<ul>
|
|
<li>Hand-writing classes for Mock Objects is not needed.
|
|
</li>
|
|
<li>Supports refactoring-safe Mock Objects: test code will not break at runtime when renaming methods or reordering method parameters
|
|
</li>
|
|
<li>Supports return values and exceptions.
|
|
</li>
|
|
<li>Supports checking the order of method calls, for one or more Mock Objects.
|
|
</li>
|
|
</ul>
|
|
<h2>
|
|
Requirements
|
|
</h2>
|
|
<ul>
|
|
<li>EasyMock only works with Java 1.5.0 and above.</li>
|
|
<li>cglib (2.2) and Objenesis (1.2) must be in the classpath to perform class mocking</li>
|
|
</ul>
|
|
<h2>
|
|
Installation
|
|
</h2>
|
|
<h3>Using Maven</h3>
|
|
EasyMock is available in the Maven central repository. Just add the following dependency to your pom.xml:
|
|
<pre>
|
|
<dependency>
|
|
<groupId>org.easymock</groupId>
|
|
<artifactId>easymock</artifactId>
|
|
<version>3.1</version>
|
|
<scope>test</scope>
|
|
</dependency>
|
|
</pre>
|
|
You can obviously use any other dependency tool compatible with the Maven repository.
|
|
|
|
<h3>Manually</h3>
|
|
<ul>
|
|
<li>Unzip the EasyMock zip file (<code>easymock-3.1.zip</code>).</li>
|
|
<li>Go into the <code>easymock-3.1</code> directory.</li>
|
|
<li>Add the EasyMock jar file (<code>easymock.jar</code>) to your classpath.</li>
|
|
<li>To perform class mocking, also add <a href="http://www.objenesis.org">Objenesis</a> and <a href="http://cglib.sourceforge.net/">Cglib</a> to your classpath.</li>
|
|
<li>The tests are in <code>easymock-3.1-tests.jar</code> and can be launched with a JUnit TestRunner
|
|
having JUnit 4.7 on top of EasyMock, cglib and Objenesis in your classpath.</li>
|
|
<li>The source code of EasyMock is stored in <code>easymock-3.1-sources.jar</code>.</li>
|
|
</ul>
|
|
<h2>
|
|
Usage
|
|
</h2>
|
|
<p>
|
|
Most parts of a software system do not work in isolation, but collaborate
|
|
with other parts to get their job done. In a lot of cases, we do not care
|
|
about using collaborators in unit testing, as we trust these collaborators.
|
|
If we <em>do</em> care about it, Mock Objects help us to test the unit under test
|
|
in isolation. Mock Objects replace collaborators of the unit under
|
|
test.
|
|
</p>
|
|
<p>
|
|
The following examples use the interface <code>Collaborator</code>:
|
|
</p>
|
|
<pre>
|
|
package org.easymock.samples;
|
|
|
|
public interface Collaborator {
|
|
void documentAdded(String title);
|
|
void documentChanged(String title);
|
|
void documentRemoved(String title);
|
|
byte voteForRemoval(String title);
|
|
byte[] voteForRemovals(String[] title);
|
|
}
|
|
</pre>
|
|
<p>
|
|
Implementors of this interface are collaborators
|
|
(in this case listeners) of a class named <code>ClassUnderTest</code>:
|
|
</p>
|
|
<pre>
|
|
public class ClassUnderTest {
|
|
// ...
|
|
public void addListener(Collaborator listener) {
|
|
// ...
|
|
}
|
|
public void addDocument(String title, byte[] document) {
|
|
// ...
|
|
}
|
|
public boolean removeDocument(String title) {
|
|
// ...
|
|
}
|
|
public boolean removeDocuments(String[] titles) {
|
|
// ...
|
|
}
|
|
}
|
|
</pre>
|
|
<p>
|
|
The code for both the class and the interface may be found
|
|
in the package <code>org.easymock.samples</code> in <code>easymock-3.1-samples.jar</code>
|
|
from the EasyMock zip delivery.
|
|
</p>
|
|
<p>
|
|
The following examples assume that you are familiar with the JUnit testing framework.
|
|
Although the tests shown here use JUnit 4, you may as well use JUnit 3 or TestNG.
|
|
</p>
|
|
<h3>
|
|
The first Mock Object
|
|
</h3>
|
|
<p>
|
|
We will now build a test case and toy around with it to understand the
|
|
functionality of the EasyMock package. <code>easymock-3.1-samples.jar</code>
|
|
contains a modified version of this test. Our first test should check
|
|
whether the removal of a non-existing document does <strong>not </strong> lead to a notification
|
|
of the collaborator. Here is the test without the definition of the
|
|
Mock Object:
|
|
</p>
|
|
<pre>
|
|
package org.easymock.samples;
|
|
|
|
import org.junit.*;
|
|
|
|
public class ExampleTest {
|
|
|
|
private ClassUnderTest classUnderTest;
|
|
private Collaborator mock;
|
|
|
|
@Before
|
|
public void setUp() {
|
|
classUnderTest = new ClassUnderTest();
|
|
classUnderTest.addListener(mock);
|
|
}
|
|
|
|
@Test
|
|
public void testRemoveNonExistingDocument() {
|
|
// This call should not lead to any notification
|
|
// of the Mock Object:
|
|
classUnderTest.removeDocument("Does not exist");
|
|
}
|
|
}
|
|
</pre>
|
|
<p>
|
|
For many tests using EasyMock,
|
|
we only need a static import of methods of <code>org.easymock.EasyMock</code>.
|
|
</p>
|
|
<pre>
|
|
import static org.easymock.EasyMock.*;
|
|
import org.junit.*;
|
|
|
|
public class ExampleTest {
|
|
|
|
private ClassUnderTest classUnderTest;
|
|
private Collaborator mock;
|
|
|
|
}
|
|
</pre>
|
|
<p>
|
|
To get a Mock Object, we need to
|
|
</p>
|
|
<ol>
|
|
<li>create a Mock Object for the interface we would like to simulate,
|
|
</li>
|
|
<li>record the expected behavior, and
|
|
</li>
|
|
<li>switch the Mock Object to replay state.
|
|
</li>
|
|
</ol>
|
|
<p>
|
|
Here is a first example:
|
|
</p>
|
|
<pre>
|
|
@Before
|
|
public void setUp() {
|
|
mock = createMock(Collaborator.class); // 1
|
|
classUnderTest = new ClassUnderTest();
|
|
classUnderTest.addListener(mock);
|
|
}
|
|
|
|
@Test
|
|
public void testRemoveNonExistingDocument() {
|
|
// 2 (we do not expect anything)
|
|
replay(mock); // 3
|
|
classUnderTest.removeDocument("Does not exist");
|
|
}
|
|
</pre>
|
|
<p>
|
|
After activation in step 3, <code>mock</code>
|
|
is a Mock Object for the <code>Collaborator</code>
|
|
interface that expects no calls. This means that if we change
|
|
our <code>ClassUnderTest</code> to call
|
|
any of the interface's methods, the Mock Object will throw
|
|
an <code>AssertionError</code>:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Unexpected method call documentRemoved("Does not exist"):
|
|
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
|
|
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:44)
|
|
at $Proxy0.documentRemoved(Unknown Source)
|
|
at org.easymock.samples.ClassUnderTest.notifyListenersDocumentRemoved(ClassUnderTest.java:74)
|
|
at org.easymock.samples.ClassUnderTest.removeDocument(ClassUnderTest.java:33)
|
|
at org.easymock.samples.ExampleTest.testRemoveNonExistingDocument(ExampleTest.java:24)
|
|
...
|
|
</pre>
|
|
|
|
<h3>
|
|
Adding Behavior
|
|
</h3>
|
|
<p>
|
|
Let us write a second test. If a document
|
|
is added on the class under test, we expect a call to <code>mock.documentAdded()</code>
|
|
on the Mock Object with the title of the document as argument:
|
|
</p>
|
|
<pre>
|
|
@Test
|
|
public void testAddDocument() {
|
|
mock.documentAdded("New Document"); // 2
|
|
replay(mock); // 3
|
|
classUnderTest.addDocument("New Document", new byte[0]);
|
|
}
|
|
</pre>
|
|
<p>
|
|
So in the record state (before calling <code>replay</code>),
|
|
the Mock Object does <em>not</em> behave like a Mock Object,
|
|
but it records method calls. After calling <code>replay</code>,
|
|
it behaves like a Mock Object, checking whether the expected
|
|
method calls are really done.
|
|
</p>
|
|
<p>
|
|
If <code>classUnderTest.addDocument("New Document", new byte[0])</code>
|
|
calls the expected method with a wrong argument, the Mock Object will complain
|
|
with an <code>AssertionError</code>:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Unexpected method call documentAdded("Wrong title"):
|
|
documentAdded("New Document"): expected: 1, actual: 0
|
|
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
|
|
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:44)
|
|
at $Proxy0.documentAdded(Unknown Source)
|
|
at org.easymock.samples.ClassUnderTest.notifyListenersDocumentAdded(ClassUnderTest.java:61)
|
|
at org.easymock.samples.ClassUnderTest.addDocument(ClassUnderTest.java:28)
|
|
at org.easymock.samples.ExampleTest.testAddDocument(ExampleTest.java:30)
|
|
...
|
|
</pre>
|
|
<p>
|
|
All missed expectations are shown, as well as all fulfilled
|
|
expectations for the unexpected call (none in this case). If the method
|
|
call is executed too often, the Mock Object complains, too:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Unexpected method call documentAdded("New Document"):
|
|
documentAdded("New Document"): expected: 1, actual: 2
|
|
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
|
|
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:44)
|
|
at $Proxy0.documentAdded(Unknown Source)
|
|
at org.easymock.samples.ClassUnderTest.notifyListenersDocumentAdded(ClassUnderTest.java:62)
|
|
at org.easymock.samples.ClassUnderTest.addDocument(ClassUnderTest.java:29)
|
|
at org.easymock.samples.ExampleTest.testAddDocument(ExampleTest.java:30)
|
|
...
|
|
</pre>
|
|
<h3>
|
|
Verifying Behavior
|
|
</h3>
|
|
<p>
|
|
There is one error that we have not handled so far: If we specify
|
|
behavior, we would like to verify that it is actually used. The current
|
|
test would pass if no method on the Mock Object is called. To verify that the
|
|
specified behavior has been used, we have to call
|
|
<code>verify(mock)</code>:
|
|
</p>
|
|
<pre>
|
|
@Test
|
|
public void testAddDocument() {
|
|
mock.documentAdded("New Document"); // 2
|
|
replay(mock); // 3
|
|
classUnderTest.addDocument("New Document", new byte[0]);
|
|
verify(mock);
|
|
}
|
|
</pre>
|
|
<p>
|
|
If the method is not called on the Mock Object, we now get the
|
|
following exception:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Expectation failure on verify:
|
|
documentAdded("New Document"): expected: 1, actual: 0
|
|
at org.easymock.internal.MocksControl.verify(MocksControl.java:70)
|
|
at org.easymock.EasyMock.verify(EasyMock.java:536)
|
|
at org.easymock.samples.ExampleTest.testAddDocument(ExampleTest.java:31)
|
|
...
|
|
</pre>
|
|
<p>
|
|
The message of the exception lists all missed expectations.
|
|
</p>
|
|
<h3>
|
|
Expecting an Explicit Number of Calls
|
|
</h3>
|
|
<p>
|
|
Up to now, our test has only considered a single method call. The next
|
|
test should check whether the addition of an already existing
|
|
document leads to a call to <code>mock.documentChanged()</code>
|
|
with the appropriate argument. To be sure, we check this three
|
|
times (hey, it is an example ;-)):
|
|
</p>
|
|
<pre>
|
|
@Test
|
|
public void testAddAndChangeDocument() {
|
|
mock.documentAdded("Document");
|
|
mock.documentChanged("Document");
|
|
mock.documentChanged("Document");
|
|
mock.documentChanged("Document");
|
|
replay(mock);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
verify(mock);
|
|
}
|
|
</pre>
|
|
<p>
|
|
To avoid the repetition of <code>mock.documentChanged("Document")</code>,
|
|
EasyMock provides a shortcut. We may specify the call count with the method
|
|
<code>times(int times)</code> on the object returned by
|
|
<code>expectLastCall()</code>. The code then looks like:
|
|
</p>
|
|
<pre>
|
|
@Test
|
|
public void testAddAndChangeDocument() {
|
|
mock.documentAdded("Document");
|
|
mock.documentChanged("Document");
|
|
expectLastCall().times(3);
|
|
replay(mock);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
verify(mock);
|
|
}
|
|
</pre>
|
|
<p>
|
|
If the method is called too often, we get an exception that
|
|
tells us that the method has been called too many times.
|
|
The failure occurs immediately at the first method call
|
|
exceeding the limit:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Unexpected method call documentChanged("Document"):
|
|
documentChanged("Document"): expected: 3, actual: 4
|
|
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
|
|
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:44)
|
|
at $Proxy0.documentChanged(Unknown Source)
|
|
at org.easymock.samples.ClassUnderTest.notifyListenersDocumentChanged(ClassUnderTest.java:67)
|
|
at org.easymock.samples.ClassUnderTest.addDocument(ClassUnderTest.java:26)
|
|
at org.easymock.samples.ExampleTest.testAddAndChangeDocument(ExampleTest.java:43)
|
|
...
|
|
</pre>
|
|
<p>
|
|
If there are too few calls, <code>verify(mock)</code>
|
|
throws an <code>AssertionError</code>:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Expectation failure on verify:
|
|
documentChanged("Document"): expected: 3, actual: 2
|
|
at org.easymock.internal.MocksControl.verify(MocksControl.java:70)
|
|
at org.easymock.EasyMock.verify(EasyMock.java:536)
|
|
at org.easymock.samples.ExampleTest.testAddAndChangeDocument(ExampleTest.java:43)
|
|
...
|
|
</pre>
|
|
<h3>
|
|
Specifying Return Values
|
|
</h3>
|
|
<p>
|
|
For specifying return values,
|
|
we wrap the expected call in <code>expect(T value)</code> and specify the return value
|
|
with the method <code>andReturn(Object returnValue)</code> on the object returned by
|
|
<code>expect(T value)</code>.
|
|
</p>
|
|
<p>
|
|
As an example, we check the workflow for document
|
|
removal. If <code>ClassUnderTest</code> gets a call for document
|
|
removal, it asks all collaborators for their vote for removal
|
|
with calls to <code>byte voteForRemoval(String title)</code> value.
|
|
Positive return values are a vote for
|
|
removal. If the sum of all values is positive, the document is removed
|
|
and <code>documentRemoved(String title)</code> is called on
|
|
all collaborators:
|
|
</p>
|
|
<pre>
|
|
@Test
|
|
public void testVoteForRemoval() {
|
|
mock.documentAdded("Document"); // expect document addition
|
|
// expect to be asked to vote for document removal, and vote for it
|
|
expect(mock.voteForRemoval("Document")).andReturn((byte) 42);
|
|
mock.documentRemoved("Document"); // expect document removal
|
|
replay(mock);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
assertTrue(classUnderTest.removeDocument("Document"));
|
|
verify(mock);
|
|
}
|
|
|
|
@Test
|
|
public void testVoteAgainstRemoval() {
|
|
mock.documentAdded("Document"); // expect document addition
|
|
// expect to be asked to vote for document removal, and vote against it
|
|
expect(mock.voteForRemoval("Document")).andReturn((byte) -42);
|
|
replay(mock);
|
|
classUnderTest.addDocument("Document", new byte[0]);
|
|
assertFalse(classUnderTest.removeDocument("Document"));
|
|
verify(mock);
|
|
}
|
|
</pre>
|
|
<p>
|
|
The type of the returned value is checked at compile time. As an example,
|
|
the following code will not compile, as the type of the provided return value
|
|
does not match the method's return value:
|
|
</p>
|
|
<pre>
|
|
expect(mock.voteForRemoval("Document")).andReturn("wrong type");
|
|
</pre>
|
|
<p>
|
|
Instead of calling <code>expect(T value)</code>
|
|
to retrieve the object for setting the return value,
|
|
we may also use the object returned by <code>expectLastCall()</code>.
|
|
Instead of
|
|
</p>
|
|
<pre>
|
|
expect(mock.voteForRemoval("Document")).andReturn((byte) 42);
|
|
</pre>
|
|
<p>
|
|
we may use
|
|
</p>
|
|
<pre>
|
|
mock.voteForRemoval("Document");
|
|
expectLastCall().andReturn((byte) 42);
|
|
</pre>
|
|
<p>
|
|
This type of specification should only be used if the line gets too long,
|
|
as it does not support type checking at compile time.
|
|
</p>
|
|
<h3>
|
|
Working with Exceptions
|
|
</h3>
|
|
<p>
|
|
For specifying exceptions (more exactly: Throwables) to be thrown, the object returned by
|
|
<code>expectLastCall()</code> and <code>expect(T value)</code> provides the method
|
|
<code>andThrow(Throwable throwable)</code>.
|
|
The method has to be called in record state after the call to the Mock Object for
|
|
which it specifies the <code>Throwable</code> to be thrown.
|
|
</p>
|
|
<p>
|
|
Unchecked exceptions (that is, <code>RuntimeException</code>, <code>Error</code>
|
|
and all their subclasses) can be thrown from every method. Checked exceptions can only be
|
|
thrown from the methods that do actually throw them.
|
|
</p>
|
|
<h3>
|
|
Creating Return Values or Exceptions
|
|
</h3>
|
|
<p>
|
|
Sometimes we would like our mock object to return a value or throw an exception
|
|
that is created at the time of the actual call. Since EasyMock 2.2, the object returned by
|
|
<code>expectLastCall()</code> and <code>expect(T value)</code> provides the method
|
|
<code>andAnswer(IAnswer answer)</code> which allows to specify an implementation of the
|
|
interface <code>IAnswer</code> that is used to create the return value or exception.
|
|
</p>
|
|
<p>
|
|
Inside an <code>IAnswer</code> callback, the arguments passed to the mock call
|
|
are available via <code>EasyMock.getCurrentArguments()</code>.
|
|
If you use these, refactorings like reordering parameters may break your tests.
|
|
You have been warned.
|
|
</p>
|
|
<p>
|
|
An alternative to <code>IAnswer</code> are the <code>andDelegateTo</code> and
|
|
<code>andStubDelegateTo</code> methods. They allow to delegate the call to a
|
|
concrete implementation of the mocked interface that will then provide the answer.
|
|
The pros are that the arguments found in <code>EasyMock.getCurrentArguments()</code>
|
|
for <code>IAnswer</code> are now passed to the method of the concrete implementation.
|
|
This is refactoring safe. The cons are that you have to provide an implementation
|
|
which is kind of doing a mock manually... Which is what you try to avoid by
|
|
using EasyMock. It can also be painful if the interface has many methods. Finally,
|
|
the type of the concrete class can't be checked statically against the mock type.
|
|
If for some reason, the concrete class isn't implementing the method that is
|
|
delegated, you will get an exception during the replay only. However, this
|
|
case should be quite rare.
|
|
</p>
|
|
<p>
|
|
To understand correctly the two options, here is an example:
|
|
</p>
|
|
<pre>
|
|
List<String> l = createMock(List.class);
|
|
|
|
// andAnswer style
|
|
expect(l.remove(10)).andAnswer(new IAnswer<String>() {
|
|
public String answer() throws Throwable {
|
|
return getCurrentArguments()[0].toString();
|
|
}
|
|
});
|
|
|
|
// andDelegateTo style
|
|
expect(l.remove(10)).andDelegateTo(new ArrayList<String>() {
|
|
@Override
|
|
public String remove(int index) {
|
|
return Integer.toString(index);
|
|
}
|
|
});
|
|
</pre>
|
|
<h3>
|
|
Changing Behavior for the Same Method Call
|
|
</h3>
|
|
<p>
|
|
It is also possible to specify a changing behavior for a method.
|
|
The methods <code>times</code>, <code>andReturn</code>, and <code>andThrow</code>
|
|
may be chained. As an example, we define <code>voteForRemoval("Document")</code> to
|
|
</p>
|
|
<ul>
|
|
<li>return 42 for the first three calls,
|
|
</li>
|
|
<li>throw a <code>RuntimeException</code> for the next four calls,
|
|
</li>
|
|
<li>return -42 once.
|
|
</li>
|
|
</ul>
|
|
<pre>
|
|
expect(mock.voteForRemoval("Document"))
|
|
.andReturn((byte) 42).times(3)
|
|
.andThrow(new RuntimeException(), 4)
|
|
.andReturn((byte) -42);
|
|
</pre>
|
|
<h3>
|
|
Relaxing Call Counts
|
|
</h3>
|
|
<p>
|
|
To relax the expected call counts, there are additional methods
|
|
that may be used instead of <code>times(int count)</code>:
|
|
</p>
|
|
<dl>
|
|
<dt><code>times(int min, int max)</code></dt>
|
|
<dd>to expect between <code>min</code> and <code>max</code> calls,</dd>
|
|
<dt><code>atLeastOnce()</code></dt>
|
|
<dd>to expect at least one call, and</dd>
|
|
<dt><code>anyTimes()</code></dt>
|
|
<dd>to expected an unrestricted number of calls.</dd>
|
|
</dl>
|
|
<p>
|
|
If no call count is specified, one call is expected. If we would like to state this
|
|
explicitely, <code>once()</code> or <code>times(1)</code> may be used.
|
|
</p>
|
|
<h3>
|
|
Strict Mocks
|
|
</h3>
|
|
<p>
|
|
On a Mock Object returned by a <code>EasyMock.createMock()</code>,
|
|
the order of method calls is not checked.
|
|
If you would like a strict Mock Object that checks the order of method calls,
|
|
use <code>EasyMock.create<i>Strict</i>Mock()</code> to create it.</p>
|
|
<p>
|
|
If an unexpected method is called on a strict Mock Object,
|
|
the message of the exception will show the method calls
|
|
expected at this point followed by the first conflicting one.
|
|
<code>verify(mock)</code> shows all missing method calls.
|
|
</p>
|
|
<h3>
|
|
Switching Order Checking On and Off
|
|
</h3>
|
|
<p>
|
|
Sometimes, it is necessary to have a Mock Object that checks the order of only some calls.
|
|
In record phase, you may switch order checking on by calling <code>checkOrder(mock, true)</code>
|
|
and switch it off by calling <code>checkOrder(mock, false)</code>.
|
|
</p>
|
|
<p>
|
|
There are two differences between a strict Mock Object and a normal Mock Object:
|
|
</p>
|
|
<ol>
|
|
<li> A strict Mock Object has order checking enabled after creation. </li>
|
|
<li> A strict Mock Object has order checking enabled after reset (see <em>Reusing a Mock Object</em>). </li>
|
|
</ol>
|
|
<h3>
|
|
Flexible Expectations with Argument Matchers
|
|
</h3>
|
|
<p>
|
|
To match an actual method call on the Mock Object with an
|
|
expectation, <code>Object</code> arguments are by default compared with
|
|
<code>equals()</code>. This may lead to problems. As an example,
|
|
we consider the following expectation:
|
|
</p>
|
|
<pre>
|
|
String[] documents = new String[] { "Document 1", "Document 2" };
|
|
expect(mock.voteForRemovals(documents)).andReturn(42);
|
|
</pre>
|
|
<p>
|
|
If the method is called with another array with the same contents,
|
|
we get an exception, as <code>equals()</code> compares object
|
|
identity for arrays:
|
|
</p>
|
|
<pre>
|
|
java.lang.AssertionError:
|
|
Unexpected method call voteForRemovals([Ljava.lang.String;@9a029e):
|
|
voteForRemovals([Ljava.lang.String;@2db19d): expected: 1, actual: 0
|
|
documentRemoved("Document 1"): expected: 1, actual: 0
|
|
documentRemoved("Document 2"): expected: 1, actual: 0
|
|
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:29)
|
|
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:44)
|
|
at $Proxy0.voteForRemovals(Unknown Source)
|
|
at org.easymock.samples.ClassUnderTest.listenersAllowRemovals(ClassUnderTest.java:88)
|
|
at org.easymock.samples.ClassUnderTest.removeDocuments(ClassUnderTest.java:48)
|
|
at org.easymock.samples.ExampleTest.testVoteForRemovals(ExampleTest.java:83)
|
|
...
|
|
</pre>
|
|
<p>
|
|
To specify that only array equality is needed for this call, we may use the method
|
|
<code>aryEq</code> that is statically imported from the <code>EasyMock</code> class:
|
|
</p>
|
|
<pre>
|
|
String[] documents = new String[] { "Document 1", "Document 2" };
|
|
expect(mock.voteForRemovals(aryEq(documents))).andReturn(42);
|
|
</pre>
|
|
<p>
|
|
If you would like to use matchers in a call, you have to specify matchers for all
|
|
arguments of the method call.
|
|
</p>
|
|
<p>
|
|
There are a couple of predefined argument matchers available.
|
|
</p>
|
|
<dl>
|
|
|
|
<dt><code>eq(X value)</code></dt>
|
|
<dd>Matches if the actual value is equals the expected value. Available for all primitive types and for objects.</dd>
|
|
|
|
<dt><code>anyBoolean()</code>, <code>anyByte()</code>, <code>anyChar()</code>, <code>anyDouble()</code>, <code>anyFloat()</code>, <code>anyInt()</code>, <code>anyLong()</code>, <code>anyObject()</code>, <code>anyObject(Class clazz)</code>, <code>anyShort()</code></dt>
|
|
<dd>Matches any value. Available for all primitive types and for objects.</dd>
|
|
|
|
<dt><code>eq(X value, X delta)</code></dt>
|
|
<dd>Matches if the actual value is equal to the given value allowing the given delta. Available for <code>float</code> and <code>double</code>.</dd>
|
|
|
|
<dt><code>aryEq(X value)</code></dt>
|
|
<dd>Matches if the actual value is equal to the given value according to <code>Arrays.equals()</code>. Available for primitive and object arrays.</dd>
|
|
|
|
<dt><code>isNull()</code>, <code>isNull(Class clazz)</code></dt>
|
|
<dd>Matches if the actual value is null. Available for objects.</dd>
|
|
|
|
<dt><code>notNull()</code>, <code>notNull(Class clazz)</code></dt>
|
|
<dd>Matches if the actual value is not null. Available for objects.</dd>
|
|
|
|
<dt><code>same(X value)</code></dt>
|
|
<dd>Matches if the actual value is the same as the given value. Available for objects.</dd>
|
|
|
|
<dt><code>isA(Class clazz)</code></dt>
|
|
<dd>Matches if the actual value is an instance of the given class, or if it is in instance of a class that extends or implements the given class. Null always return false. Available for objects.</dd>
|
|
|
|
<dt><code>lt(X value)</code>, <code>leq(X value)</code>, <code>geq(X value)</code>, <code>gt(X value)</code></dt>
|
|
<dd>Matches if the actual value is less/less or equal/greater or equal/greater than the given value. Available for all numeric primitive types and <code>Comparable</code>.</dd>
|
|
|
|
<dt><code>startsWith(String prefix), contains(String substring), endsWith(String suffix)</code></dt>
|
|
<dd>Matches if the actual value starts with/contains/ends with the given value. Available for <code>String</code>s.</dd>
|
|
|
|
<dt><code>matches(String regex), find(String regex)</code></dt>
|
|
<dd>Matches if the actual value/a substring of the actual value matches the given regular expression. Available for <code>String</code>s.</dd>
|
|
|
|
<dt><code>and(X first, X second)</code></dt>
|
|
<dd>Matches if the matchers used in <code>first</code> and <code>second</code> both match. Available for all primitive types and for objects.</dd>
|
|
|
|
<dt><code>or(X first, X second)</code></dt>
|
|
<dd>Matches if one of the matchers used in <code>first</code> and <code>second</code> match. Available for all primitive types and for objects.</dd>
|
|
|
|
<dt><code>not(X value)</code></dt>
|
|
<dd>Matches if the matcher used in <code>value</code> does not match.</dd>
|
|
|
|
<dt><code>cmpEq(X value)</code></dt>
|
|
<dd>Matches if the actual value is equals according to <code>Comparable.compareTo(X o)</code>. Available for all numeric primitive types and <code>Comparable</code>.</dd>
|
|
|
|
<dt><code>cmp(X value, Comparator<X> comparator, LogicalOperator operator)</code></dt>
|
|
<dd>Matches if <code>comparator.compare(actual, value) operator 0</code> where the operator is <,<=,>,>= or ==. Available for objects.</dd>
|
|
|
|
<dt><code>capture(Capture<T> capture)</code>, <code>captureXXX(Capture<T> capture)</code></dt>
|
|
<dd>Matches any value but captures it in the <code>Capture</code> parameter for later access. You can do <code>and(someMatcher(...), capture(c))</code> to
|
|
capture a parameter from a specific call to the method. You can also specify a <code>CaptureType</code> telling that a given <code>Capture</code> should keep
|
|
the first, the last, all or no captured values.</dd>
|
|
|
|
</dl>
|
|
|
|
<h3>
|
|
Defining your own Argument Matchers
|
|
</h3>
|
|
<p>
|
|
Sometimes it is desirable to define own argument matchers. Let's say that an
|
|
argument matcher is needed that matches an exception if the given exception has the same type and an equal message.
|
|
It should be used this way:
|
|
</p>
|
|
<pre>
|
|
IllegalStateException e = new IllegalStateException("Operation not allowed.")
|
|
expect(mock.logThrowable(eqException(e))).andReturn(true);
|
|
</pre>
|
|
<p>
|
|
Two steps are necessary to achieve this: The new argument matcher has to be defined,
|
|
and the static method <code>eqException</code> has to be declared.
|
|
</p>
|
|
<p>
|
|
To define the new argument matcher, we implement the interface <code>org.easymock.IArgumentMatcher</code>.
|
|
This interface contains two methods: <code>matches(Object actual)</code> checks whether the actual argument
|
|
matches the given argument, and <code>appendTo(StringBuffer buffer)</code> appends a string representation
|
|
of the argument matcher to the given string buffer. The implementation is straightforward:
|
|
</p>
|
|
<pre>
|
|
import org.easymock.IArgumentMatcher;
|
|
|
|
public class ThrowableEquals implements IArgumentMatcher {
|
|
private Throwable expected;
|
|
|
|
public ThrowableEquals(Throwable expected) {
|
|
this.expected = expected;
|
|
}
|
|
|
|
public boolean matches(Object actual) {
|
|
if (!(actual instanceof Throwable)) {
|
|
return false;
|
|
}
|
|
String actualMessage = ((Throwable) actual).getMessage();
|
|
return expected.getClass().equals(actual.getClass())
|
|
&& expected.getMessage().equals(actualMessage);
|
|
}
|
|
|
|
public void appendTo(StringBuffer buffer) {
|
|
buffer.append("eqException(");
|
|
buffer.append(expected.getClass().getName());
|
|
buffer.append(" with message \"");
|
|
buffer.append(expected.getMessage());
|
|
buffer.append("\"")");
|
|
|
|
}
|
|
}
|
|
</pre>
|
|
<p>
|
|
The method <code>eqException</code> must create the argument matcher with the given Throwable,
|
|
report it to EasyMock via the static method <code>reportMatcher(IArgumentMatcher matcher)</code>,
|
|
and return a value so that it may be used inside the call
|
|
(typically <code>0</code>, <code>null</code> or <code>false</code>). A first attempt may look like:
|
|
</p>
|
|
<pre>
|
|
public static Throwable eqException(Throwable in) {
|
|
EasyMock.reportMatcher(new ThrowableEquals(in));
|
|
return null;
|
|
}
|
|
</pre>
|
|
<p>
|
|
However, this only works if the method <code>logThrowable</code> in the example usage accepts
|
|
<code>Throwable</code>s, and does not require something more specific like a <code>RuntimeException</code>.
|
|
In the latter case, our code sample would not compile:
|
|
</p>
|
|
<pre>
|
|
IllegalStateException e = new IllegalStateException("Operation not allowed.")
|
|
expect(mock.logThrowable(eqException(e))).andReturn(true);
|
|
</pre>
|
|
<p>
|
|
Java 5.0 to the rescue: Instead of defining <code>eqException</code> with a <code>Throwable</code> as
|
|
parameter and return value, we use a generic type that extends <code>Throwable</code>:
|
|
</p>
|
|
<pre>
|
|
public static <T extends Throwable> T eqException(T in) {
|
|
reportMatcher(new ThrowableEquals(in));
|
|
return null;
|
|
}
|
|
</pre>
|
|
<h3>
|
|
Reusing a Mock Object
|
|
</h3>
|
|
<p>
|
|
Mock Objects may be reset by <code>reset(mock)</code>.
|
|
</p>
|
|
<p>
|
|
If needed, a mock can also be converted from one type to another by calling <code>resetToNice(mock)</code>,
|
|
<code>resetToDefault(mock)</code> ou <code>resetToStrict(mock)</code>.
|
|
</p>
|
|
<h3>
|
|
Using Stub Behavior for Methods
|
|
</h3>
|
|
<p>
|
|
Sometimes, we would like our Mock Object to respond to some method calls, but we do not want to
|
|
check how often they are called, when they are called, or even if they are called at all.
|
|
This stub behavoir may be defined by using the methods <code>andStubReturn(Object value)</code>,
|
|
<code>andStubThrow(Throwable throwable)</code>, <code>andStubAnswer(IAnswer<Tgt; answer)</code>
|
|
and <code>asStub()</code>. The following code
|
|
configures the MockObject to answer 42 to <code>voteForRemoval("Document")</code> once
|
|
and -1 for all other arguments:
|
|
</p>
|
|
<pre>
|
|
expect(mock.voteForRemoval("Document")).andReturn(42);
|
|
expect(mock.voteForRemoval(not(eq("Document")))).andStubReturn(-1);
|
|
</pre>
|
|
<h3>
|
|
Nice Mocks
|
|
</h3>
|
|
<p>
|
|
On a Mock Object returned by <code>createMock()</code> the default behavior for all methods is to throw an
|
|
<code>AssertionError</code> for all unexpected method calls.
|
|
If you would like a "nice" Mock Object that by default allows all method calls and returns
|
|
appropriate empty values (<code>0</code>, <code>null</code> or <code>false</code>), use <code>create<i>Nice</i>Mock()</code> instead.
|
|
</p>
|
|
|
|
<a id="Object_Methods"/><h3>Object Methods</h3>
|
|
<p>
|
|
The behavior for the four Object methods <code>equals()</code>,
|
|
<code>hashCode()</code>, <code>toString()</code> and <code>finalize()</code>
|
|
cannot be changed for Mock Objects created with EasyMock,
|
|
even if they are part of the interface for which the
|
|
Mock Object is created.
|
|
</p>
|
|
<h3>Checking Method Call Order Between Mocks</h3>
|
|
<p>
|
|
Up to this point, we have seen a mock object as a single object that is configured by static methods
|
|
on the class <code>EasyMock</code>. But many of these static methods just identify the hidden control of the Mock Object
|
|
and delegate to it. A Mock Control is an object implementing the <code>IMocksControl</code> interface.
|
|
</p>
|
|
<p>
|
|
So instead of
|
|
</p>
|
|
<pre>
|
|
IMyInterface mock = createStrictMock(IMyInterface.class);
|
|
replay(mock);
|
|
verify(mock);
|
|
reset(mock);
|
|
</pre>
|
|
<p>
|
|
we may use the equivalent code:
|
|
</p>
|
|
<pre>
|
|
IMocksControl ctrl = createStrictControl();
|
|
IMyInterface mock = ctrl.createMock(IMyInterface.class);
|
|
ctrl.replay();
|
|
ctrl.verify();
|
|
ctrl.reset();
|
|
</pre>
|
|
<p>
|
|
The IMocksControl allows to create more than one Mock Object, and so it is possible to check the order of method calls
|
|
between mocks. As an example, we set up two mock objects for the interface <code>IMyInterface</code>, and we expect the calls
|
|
<code>mock1.a()</code> and <code>mock2.a()</code> ordered, then an open number of calls to <code>mock1.c()</code>
|
|
and <code>mock2.c()</code>, and finally <code>mock2.b()</code> and <code>mock1.b()</code>, in this order:
|
|
</p>
|
|
<pre>
|
|
IMocksControl ctrl = createStrictControl();
|
|
IMyInterface mock1 = ctrl.createMock(IMyInterface.class);
|
|
IMyInterface mock2 = ctrl.createMock(IMyInterface.class);
|
|
|
|
mock1.a();
|
|
mock2.a();
|
|
|
|
ctrl.checkOrder(false);
|
|
|
|
mock1.c();
|
|
expectLastCall().anyTimes();
|
|
mock2.c();
|
|
expectLastCall().anyTimes();
|
|
|
|
ctrl.checkOrder(true);
|
|
|
|
mock2.b();
|
|
mock1.b();
|
|
|
|
ctrl.replay();
|
|
</pre>
|
|
<h3>Naming Mock Objects</h3>
|
|
<p>
|
|
Mock Objects can be named at creation using
|
|
<code>createMock(String name, Class<T> toMock)</code>,
|
|
<code>createStrictMock(String name, Class<T> toMock)</code> or
|
|
<code>createNiceMock(String name, Class<T> toMock)</code>.
|
|
The names will be shown in exception failures.
|
|
</p>
|
|
<h3>Serializing Mocks</h3>
|
|
<p>
|
|
Mocks can be serialized at any time during their life. However, there are some obvious contraints:
|
|
</p>
|
|
<ul>
|
|
<li>All used matchers should be serializable (all genuine EasyMock ones are)
|
|
</li>
|
|
<li>Recorded parameters should also be serializable
|
|
</li>
|
|
</ul>
|
|
<h3>Multithreading</h3>
|
|
<p>
|
|
During recording, a mock is <b>not</b> thread-safe. So a giving mock (or mocks linked to the same <code>IMocksControl</code>)
|
|
can only be recorded from a single thread. However, different mocks can be recorded simultaneously in different threads.
|
|
</p>
|
|
<p>
|
|
During the replay phase, mocks are by default thread-safe. This can be change for a given mock if <code>makeThreadSafe(mock, false)</code>
|
|
is called during the recording phase. This can prevent deadlocks in some rare situations.
|
|
</p>
|
|
<p>
|
|
Finally, calling <code>checkIsUsedInOneThread(mock, true)</code> on a mock will make sure the mock is used in only one thread and
|
|
throw an exception otherwise. This can be handy to make sure a thread-unsafe mocked object is used correctly.
|
|
</p>
|
|
<h3>EasyMockSupport</h3>
|
|
<p>
|
|
<code>EasyMockSupport</code> is a class that meant to be used as a helper or base class to your test cases. It will automatically registers all
|
|
created mocks (or in fact all created controls) and to replay, reset or verify them in batch instead of explicitly. Here's a JUnit example:
|
|
</p>
|
|
<pre>
|
|
public class SupportTest extends EasyMockSupport {
|
|
|
|
private Collaborator firstCollaborator;
|
|
private Collaborator secondCollaborator;
|
|
private ClassTested classUnderTest;
|
|
|
|
@Before
|
|
public void setup() {
|
|
classUnderTest = new ClassTested();
|
|
}
|
|
|
|
@Test
|
|
public void addDocument() {
|
|
// creation phase
|
|
firstCollaborator = createMock(Collaborator.class);
|
|
secondCollaborator = createMock(Collaborator.class);
|
|
classUnderTest.addListener(firstCollaborator);
|
|
classUnderTest.addListener(secondCollaborator);
|
|
|
|
// recording phase
|
|
firstCollaborator.documentAdded("New Document");
|
|
secondCollaborator.documentAdded("New Document");
|
|
|
|
replayAll(); // replay all mocks at once
|
|
|
|
// test
|
|
classUnderTest.addDocument("New Document", new byte[0]);
|
|
|
|
verifyAll(); // verify all mocks at once
|
|
}
|
|
}
|
|
</pre>
|
|
<h3>Altering EasyMock default behavior</h3>
|
|
<p>
|
|
EasyMock provides a property mecanisim allowing to alter its behavior. It mainly aims
|
|
at allowing to use a legacy behavior on a new version. Currently supported properties are:
|
|
</p>
|
|
<dl>
|
|
<dt><code>easymock.notThreadSafeByDefault</code></dt>
|
|
<dd>If true, a mock won't be thread-safe by default. Possible values are "true" or "false". Default is false</dd>
|
|
<dt><code>easymock.enableThreadSafetyCheckByDefault</code></dt>
|
|
<dd>If true, thread-safety check feature will be on by default. Possible values are "true" or "false". Default is false</dd>
|
|
<dt><code>easymock.disableClassMocking</code></dt>
|
|
<dd>Do not allow class mocking (only allow interface mocking). Possible values are "true" or "false". Default is false.</dd>
|
|
</dl>
|
|
<p>
|
|
Properties can be set in three ways. Each step in the list can overwrite
|
|
previous ones.
|
|
</p>
|
|
<ul>
|
|
<li>In an <code>easymock.properties</code> file set in the classpath default package
|
|
</li>
|
|
<li>As a system property
|
|
</li>
|
|
<li>By calling <code>EasyMock.setEasyMockProperty</code>. Constants are available
|
|
in the <code>EasyMock</code> class
|
|
</li>
|
|
</ul>
|
|
<h3>Backward Compatibility</h3>
|
|
<p>EasyMock 3 still has a Class Extension project (although deprecated) to
|
|
allow an easier migration from EasyMock 2 to EasyMock 3. It is a source not a binary
|
|
compatibility. So the code will need to be recompiled.
|
|
</p>
|
|
<p>EasyMock 2.1 introduced a callback feature that has been removed in EasyMock 2.2,
|
|
as it was too complex. Since EasyMock 2.2, the <code>IAnswer</code> interface
|
|
provides the functionality for callbacks.
|
|
</p>
|
|
<h3>OSGi</h3>
|
|
<p>
|
|
EasyMock jar can be used as an OSGi bundle. It exports <code>org.easymock</code>,
|
|
<code>org.easymock.internal</code> and <code>org.easymock.internal.matchers</code>
|
|
packages. However, to import the two latter, you need to specify the <code>poweruser</code>
|
|
attribute at true (<code>poweruser=true</code>). These packages are meant to be
|
|
used to extend EasyMock so they usually don't need to be imported.
|
|
</p>
|
|
<h3>Partial mocking</h3>
|
|
<p>
|
|
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.
|
|
</p>
|
|
<p>
|
|
In this case, the first thing to do is to consider a refactoring since
|
|
most of the time this problem caused by a bad design. If it's not
|
|
the case or if you can't do otherwise because of some development constraints,
|
|
here's the solution.
|
|
</p>
|
|
<pre>
|
|
ToMock mock = createMockBuilder(ToMock.class)
|
|
.addMockedMethod("mockedMethod").createMock();
|
|
</pre>
|
|
<p>In this case only the methods added with <code>addMockedMethod(s)</code> will be
|
|
mocked (<code>mockedMethod()</code> in the example). The others will still
|
|
behave as they used to. One exception: abstract methods are conveniently mocked by default.
|
|
</p>
|
|
<p><code>createMockBuilder</code> returns a <code>IMockBuilder</code> interface. It contains various methods to
|
|
easily create a partial mock. Have a look at the javadoc.
|
|
</p>
|
|
<p>
|
|
<b>Remark:</b> EasyMock provides a default behavior for Object's methods (<i>equals, hashCode, toString, finalize</i>).
|
|
However, for a partial mock, if these methods are not mocked explicitly, they will have their normal behavior
|
|
instead of EasyMock default's one.
|
|
</p>
|
|
<h3>Self testing</h3>
|
|
<p>
|
|
It is possible to create a mock by calling one of its constructor. This can be handy when a
|
|
class method needs to be tested but the class other methods, mocked. For that you should do
|
|
something like
|
|
</p>
|
|
<pre>
|
|
ToMock mock = createMockBuilder(ToMock.class)
|
|
.withConstructor(1, 2, 3); // 1, 2, 3 are the constructor parameters
|
|
</pre>
|
|
<p>
|
|
See the <code>ConstructorCalledMockTest</code> for an example.
|
|
</p>
|
|
<h3>Replace default class instantiator</h3>
|
|
<p>
|
|
For some reason (usually an unsupported JVM), it is possible that EasyMock isn't able to mock
|
|
a class mock in your environment. Under the hood, class instantiation is implemented with a factory
|
|
pattern. In case of failure, you can replace the default instantiator with:
|
|
</p>
|
|
<ul>
|
|
<li>The good old <code>DefaultClassInstantiator</code> which works well with Serializable classes
|
|
and otherwise tries to guess the best constructor and parameters to use.</li>
|
|
<li>You own instantiator which only needs to implement <code>IClassInstantiator</code>.</li>
|
|
</ul>
|
|
<p>
|
|
You set this new instantiator using <code>ClassInstantiatorFactory.setInstantiator()</code>.
|
|
You can set back the default one with <code>setDefaultInstantiator()</code>.
|
|
</p>
|
|
<p>
|
|
<b>Important:</b>
|
|
The instantiator is kept statically so it will stick between your unit tests. Make sure you
|
|
reset it if needed.
|
|
</p>
|
|
<h3>Serialize a class mock</h3>
|
|
<p>
|
|
A class mock can also be serialized. However, since it extends a serializable class, this class
|
|
might have defined a special behavior using for instance <code>writeObject</code>. These methods
|
|
will still be called when serializing the mock and might fail. The workaround is usually to call
|
|
a constructor when creating the mock.
|
|
</p>
|
|
<p>
|
|
Also, de-serializing the mock in a different class loader than the serialization might fail. It wasn't tested.
|
|
</p>
|
|
<h3>Class Mocking Limitations</h3>
|
|
<ul>
|
|
<li>To be coherent with interface mocking, EasyMock provides a built-in behavior
|
|
for <code>equals()</code>, <code>toString()</code>, <code>hashCode()</code> and <code>finalize()</code>
|
|
even for class mocking. It means that you cannot record your own behavior for
|
|
these methods. This limitation is considered to be a feature
|
|
that prevents you from having to care about these methods.
|
|
</li>
|
|
<li>Final methods cannot be mocked. If called, their normal code will be executed.
|
|
</li>
|
|
<li>Private methods cannot be mocked. If called, their normal code will be executed.
|
|
During partial mocking, if your method under test is calling some private methods,
|
|
you will need to test them as well since you cannot mock them.
|
|
</li>
|
|
<li>Class instantiation is performed using
|
|
<a href="http://objenesis.googlecode.com/svn/docs/index.html">Objenesis</a>.
|
|
Supported JVMs are listed
|
|
<a href="http://code.google.com/p/objenesis/wiki/ListOfCurrentlySupportedVMs">here</a>.
|
|
</li>
|
|
</ul>
|
|
|
|
<h2>
|
|
EasyMock Development
|
|
</h2>
|
|
<p>
|
|
EasyMock has been developed by Tammo Freese at OFFIS. It is maintained by Henri Tremblay
|
|
since 2007. The development of EasyMock is hosted on <a href="http://sourceforge.net/projects/easymock/">SourceForge</a>
|
|
to allow other developers and companies to contribute.
|
|
</p>
|
|
<p>
|
|
Class mocking (previously known as EasyMock Class Extension) was initially developed
|
|
by Joel Shellman, Chad Woolley and Henri Tremblay on the files section of Yahoo!Groups.
|
|
</p>
|
|
<p>
|
|
Thanks to the people who gave feedback or provided patches, including
|
|
Nascif Abousalh-Neto, Dave Astels, Francois Beausoleil, George Dinwiddie, Shane Duan,
|
|
Wolfgang Frech, Steve Freeman, Oren Gross, John D. Heintz, Dale King, Brian Knorr,
|
|
Dierk Koenig, Chris Kreussling, Robert Leftwich, Patrick Lightbody, Johannes Link,
|
|
Rex Madden, David McIntosh, Karsten Menne, Bill Michell,
|
|
Stephan Mikaty, Ivan Moore, Ilja Preuss, Justin Sampson, Markus Schmidlin, Richard Scott,
|
|
Joel Shellman, Jiří Mareš, Alexandre de Pellegrin
|
|
Shaun Smith, Marco Struck, Ralf Stuckert, Victor Szathmary, Bill Uetrecht,
|
|
Frank Westphal, Chad Woolley, Bernd Worsch,
|
|
Rodrigo Damazio, Bruno Fonseca, Ben Hutchison and numerous others.
|
|
</p>
|
|
<p>
|
|
Please check the <a href="http://www.easymock.org">EasyMock home page</a> for new versions,
|
|
and send bug reports and suggestions to the
|
|
<a href="mailto:easymock@yahoogroups.com?subject=EasyMock ${project.version} feedback">EasyMock Yahoo!Group</a>.
|
|
If you would like to subscribe to the EasyMock Yahoo!Group, send a message to
|
|
<a href="mailto:easymock-subscribe@yahoogroups.com">easymock-subscribe@yahoogroups.com</a>.
|
|
</p>
|
|
<h3>
|
|
EasyMock Version 3.1 (2011-11-10) Release Notes
|
|
</h3>
|
|
<p>
|
|
New in version 3.1:
|
|
</p>
|
|
<ul>
|
|
<li>NoClassDefFoundError on calling EasyMock.replay/reset/verify on an interface mock without cglib in the classpath (EASYMOCK-40)
|
|
</li>
|
|
<li>Can compile in Java 7 (capture methods for primitive types are renamed and deprecated) (EASYMOCK-100)
|
|
</li>
|
|
<li>Fix memory leak in cglib callback registration process (EASYMOCK-89)
|
|
</li>
|
|
<li>Ignore calls to finalize on a mock (EASYMOCK-21)
|
|
</li>
|
|
<li>MockBuilder.addMockedMethod should fail for final methods (EASYMOCK-44)
|
|
</li>
|
|
<li>Bridge method should not be considered by MockBuilder.addMockedMethod (EASYMOCK-90)
|
|
</li>
|
|
<li>Perform a smoke test with PowerMock to make sure it is still working (EASYMOCK-88)
|
|
</li>
|
|
<li>Add the class or interface name in error message for each invocation (EASYMOCK-104)
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
New in version 3.0:
|
|
</p>
|
|
<ul>
|
|
<li>EasyMock CE is now merged into EasyMock (2325762)
|
|
</li>
|
|
<li>Add "boolean capture(...)" for completude (but I don't think it's useful)
|
|
</li>
|
|
<li>Can't answer by delegating to a protected method (2891256)
|
|
</li>
|
|
<li>Failure during recording phase can impact following tests (2914683)
|
|
</li>
|
|
<li>Return a specific error when null is recorded as return value on a method returning a primitive type (2936175)
|
|
</li>
|
|
<li>Can disable class mocking with <code>EasyMock.DISABLE_CLASS_MOCKING</code>
|
|
</li>
|
|
<li>Remove deprecated classes from EasyMock 1
|
|
</li>
|
|
<li>Should not fail on a mock not having a <code>toString</code> method (2937916)
|
|
</li>
|
|
<li>Improved error message when matchers are mixed with raw params during method recording (2860190)
|
|
</li>
|
|
<li>Check there are still results available in a recorded behaviour before trying to match with it (2940400)
|
|
</li>
|
|
<li>Allow to mock classes from an Eclipse plugin (2994002)
|
|
</li>
|
|
<li>Add <code>isNull(Class<T>)</code>, <code>notNull(Class<T>)</code> and <code>anyObject(Class<T>)</code> for easier generic handling (2958636)
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
For older release notes, see <a href="Documentation.html">EasyMock 2 and EasyMock 2 Class Extension documentations</a>.
|
|
</p>
|
|
</div>
|
|
</body>
|
|
</html>
|