[easymock] 40/41: Imported Upstream version 3.2+ds

Markus Koschany apo-guest at moszumanska.debian.org
Tue Nov 25 16:49:13 GMT 2014


This is an automated email from the git hooks/post-receive script.

apo-guest pushed a commit to branch master
in repository easymock.

commit 5f3e743593979eb9d910144d042345e2b2a06cc2
Author: Markus Koschany <apo at gambaru.de>
Date:   Tue Nov 25 17:48:12 2014 +0100

    Imported Upstream version 3.2+ds
---
 Documentation.html                                 | 2179 ++++++-----
 Documentation_fr.html                              | 2293 ++++++------
 LICENSE.txt                                        |  202 ++
 License.html                                       |   33 -
 easymock.css                                       |   57 +-
 .../org/easymock/samples/AnnotatedMockTest.java    |   46 +
 .../org/easymock/samples/BasicClassMockTest.java   |  101 +
 samples/org/easymock/samples/ClassTested.java      |   91 +
 samples/org/easymock/samples/ClassUnderTest.java   |   93 -
 samples/org/easymock/samples/Collaborator.java     |   48 +-
 .../samples/ConstructorCalledMockTest.java         |   90 +
 samples/org/easymock/samples/ExampleTest.java      |  271 +-
 .../org/easymock/samples/PartialClassMockTest.java |   80 +
 samples/org/easymock/samples/SupportTest.java      |   70 +
 samples/org/easymock/samples/ThrowableEquals.java  |   93 +-
 src/org/easymock/AbstractMatcher.java              |  125 -
 src/org/easymock/ArgumentsMatcher.java             |   42 -
 src/org/easymock/Capture.java                      |  206 +-
 src/org/easymock/CaptureType.java                  |   44 +
 src/org/easymock/ConstructorArgs.java              |  103 +
 src/org/easymock/EasyMock.java                     | 3828 +++++++++++---------
 src/org/easymock/EasyMockRunner.java               |   58 +
 src/org/easymock/EasyMockSupport.java              |  728 ++++
 src/org/easymock/IAnswer.java                      |   63 +-
 src/org/easymock/IArgumentMatcher.java             |   87 +-
 src/org/easymock/IExpectationSetters.java          |  269 +-
 src/org/easymock/IMockBuilder.java                 |  336 ++
 src/org/easymock/IMocksControl.java                |  266 +-
 src/org/easymock/LogicalOperator.java              |  114 +-
 src/org/easymock/Mock.java                         |   42 +
 src/org/easymock/MockControl.java                  |  597 ---
 src/org/easymock/MockType.java                     |   31 +
 src/org/easymock/TestSubject.java                  |   34 +
 src/org/easymock/internal/AlwaysMatcher.java       |   21 -
 .../internal/AndroidClassProxyFactory.java         |  101 +
 src/org/easymock/internal/AndroidSupport.java      |   37 +
 src/org/easymock/internal/ArgumentToString.java    |   97 +
 src/org/easymock/internal/ArrayMatcher.java        |   24 -
 .../easymock/internal/AssertionErrorWrapper.java   |   54 +-
 .../easymock/internal/BridgeMethodResolver.java    |  444 +++
 .../internal/ClassInstantiatorFactory.java         |   81 +
 src/org/easymock/internal/ClassProxyFactory.java   |  285 ++
 .../internal/DefaultClassInstantiator.java         |  206 ++
 src/org/easymock/internal/EasyMockProperties.java  |  139 +
 src/org/easymock/internal/EqualsMatcher.java       |   13 -
 src/org/easymock/internal/ErrorMessage.java        |   60 +
 src/org/easymock/internal/ExpectedInvocation.java  |  241 +-
 .../internal/ExpectedInvocationAndResult.java      |   71 +-
 .../internal/ExpectedInvocationAndResults.java     |   81 +-
 src/org/easymock/internal/IClassInstantiator.java  |   36 +
 .../easymock/internal/ILegacyMatcherMethods.java   |   16 -
 src/org/easymock/internal/ILegacyMethods.java      |   13 -
 src/org/easymock/internal/IMocksBehavior.java      |   70 +-
 src/org/easymock/internal/IMocksControlState.java  |   96 +-
 src/org/easymock/internal/IProxyFactory.java       |   58 +-
 src/org/easymock/internal/Invocation.java          |  391 +-
 src/org/easymock/internal/JavaProxyFactory.java    |   52 +-
 src/org/easymock/internal/LastControl.java         |  245 +-
 .../easymock/internal/LegacyMatcherProvider.java   |   56 -
 .../internal/MethodSerializationWrapper.java       |  147 +-
 src/org/easymock/internal/MockBuilder.java         |  239 ++
 .../easymock/internal/MockInvocationHandler.java   |   93 +-
 src/org/easymock/internal/MocksBehavior.java       |  366 +-
 src/org/easymock/internal/MocksControl.java        |  671 ++--
 src/org/easymock/internal/ObjectMethodsFilter.java |  223 +-
 .../internal/ObjenesisClassInstantiator.java       |   29 +
 src/org/easymock/internal/Range.java               |  158 +-
 src/org/easymock/internal/RecordState.java         |  686 ++--
 src/org/easymock/internal/ReflectionUtils.java     |  233 ++
 src/org/easymock/internal/ReplayState.java         |  288 +-
 src/org/easymock/internal/Result.java              |  186 +-
 src/org/easymock/internal/Results.java             |  185 +-
 .../easymock/internal/RuntimeExceptionWrapper.java |   54 +-
 src/org/easymock/internal/ThrowableWrapper.java    |   54 +-
 src/org/easymock/internal/UnorderedBehavior.java   |  205 +-
 src/org/easymock/internal/matchers/And.java        |   98 +-
 src/org/easymock/internal/matchers/Any.java        |   70 +-
 .../easymock/internal/matchers/ArrayEquals.java    |  144 +-
 src/org/easymock/internal/matchers/Captures.java   |   90 +-
 src/org/easymock/internal/matchers/Compare.java    |  100 +-
 .../easymock/internal/matchers/CompareEqual.java   |   65 +-
 src/org/easymock/internal/matchers/CompareTo.java  |   93 +-
 src/org/easymock/internal/matchers/Contains.java   |   71 +-
 src/org/easymock/internal/matchers/EndsWith.java   |   70 +-
 src/org/easymock/internal/matchers/Equals.java     |  127 +-
 .../internal/matchers/EqualsWithDelta.java         |   82 +-
 src/org/easymock/internal/matchers/Find.java       |   73 +-
 .../easymock/internal/matchers/GreaterOrEqual.java |   65 +-
 .../easymock/internal/matchers/GreaterThan.java    |   65 +-
 src/org/easymock/internal/matchers/InstanceOf.java |   70 +-
 .../easymock/internal/matchers/LessOrEqual.java    |   65 +-
 src/org/easymock/internal/matchers/LessThan.java   |   65 +-
 src/org/easymock/internal/matchers/Matches.java    |   71 +-
 src/org/easymock/internal/matchers/Not.java        |   74 +-
 src/org/easymock/internal/matchers/NotNull.java    |   70 +-
 src/org/easymock/internal/matchers/Null.java       |   68 +-
 src/org/easymock/internal/matchers/Or.java         |   98 +-
 src/org/easymock/internal/matchers/Same.java       |   85 +-
 src/org/easymock/internal/matchers/StartsWith.java |   71 +-
 tests/org/easymock/tests/ArgumentToStringTest.java |   83 +
 tests/org/easymock/tests/ArgumentsMatcherTest.java |  143 -
 tests/org/easymock/tests/ArrayMatcherTest.java     |  108 -
 .../org/easymock/tests/BaseEasyMockRunnerTest.java |   26 +
 tests/org/easymock/tests/CapturesMatcherTest.java  |  114 +-
 tests/org/easymock/tests/CglibTest.java            |   70 +
 .../tests/ClassInstantiatorFactoryTest.java        |   63 +
 tests/org/easymock/tests/ConstructorTest.java      |   72 +
 .../tests/DefaultClassInstantiatorTest.java        |  217 ++
 tests/org/easymock/tests/DefaultMatcherTest.java   |   94 -
 tests/org/easymock/tests/EqualsMatcherTest.java    |   33 -
 tests/org/easymock/tests/ErrorMessageTest.java     |   59 +
 .../org/easymock/tests/ExpectedMethodCallTest.java |   85 +-
 tests/org/easymock/tests/GenericTest.java          |  123 +
 tests/org/easymock/tests/IMethods.java             |  190 +-
 tests/org/easymock/tests/IVarArgs.java             |   68 +-
 tests/org/easymock/tests/InvocationTest.java       |  204 +-
 tests/org/easymock/tests/LegacyBehaviorTests.java  |   66 -
 tests/org/easymock/tests/LimitationsTest.java      |   85 +
 .../org/easymock/tests/MatchableArgumentsTest.java |   99 +-
 .../tests/MethodSerializationWrapperTest.java      |   68 +-
 tests/org/easymock/tests/MockClassControlTest.java |  168 +
 tests/org/easymock/tests/MockNameTest.java         |   59 +-
 tests/org/easymock/tests/MockTypeTest.java         |  104 +
 tests/org/easymock/tests/MockingTest.java          |  147 +
 ...ceMockControlLongCompatibleReturnValueTest.java |  120 +-
 tests/org/easymock/tests/NiceMockControlTest.java  |  109 +-
 tests/org/easymock/tests/ObjectMethodsTest.java    |  171 +-
 .../RecordStateInvalidDefaultReturnValueTest.java  |  136 +-
 .../RecordStateInvalidDefaultThrowableTest.java    |  155 +-
 .../tests/RecordStateInvalidMatcherTest.java       |   75 -
 .../tests/RecordStateInvalidRangeTest.java         |  166 +-
 .../tests/RecordStateInvalidReturnValueTest.java   |  214 +-
 .../tests/RecordStateInvalidStateChangeTest.java   |  140 +-
 .../tests/RecordStateInvalidThrowableTest.java     |  158 +-
 .../tests/RecordStateInvalidUsageTest.java         |  220 +-
 .../tests/RecordStateMethodCallMissingTest.java    |  263 +-
 .../tests/ReplayStateInvalidCallsTest.java         |  289 +-
 .../tests/ReplayStateInvalidUsageTest.java         |  583 +--
 tests/org/easymock/tests/ResultTest.java           |   83 +-
 tests/org/easymock/tests/StacktraceTest.java       |  223 +-
 tests/org/easymock/tests/UsageCallCountTest.java   |  276 +-
 .../tests/UsageDefaultReturnValueTest.java         |  256 +-
 .../tests/UsageExpectAndDefaultReturnTest.java     |  160 +-
 .../tests/UsageExpectAndDefaultThrowTest.java      |  315 +-
 .../easymock/tests/UsageExpectAndReturnTest.java   |  404 ++-
 .../easymock/tests/UsageExpectAndThrowTest.java    |  780 ++--
 .../tests/UsageFloatingPointReturnValueTest.java   |  117 +-
 .../tests/UsageLongCompatibleReturnValueTest.java  |  204 +-
 .../tests/UsageOverloadedDefaultValueTest.java     |  223 +-
 .../easymock/tests/UsageOverloadedMethodTest.java  |  317 +-
 tests/org/easymock/tests/UsageRangeTest.java       |  203 +-
 tests/org/easymock/tests/UsageStrictMockTest.java  |  471 ++-
 tests/org/easymock/tests/UsageTest.java            |  422 ++-
 tests/org/easymock/tests/UsageThrowableTest.java   |  286 +-
 tests/org/easymock/tests/UsageUnorderedTest.java   |  109 +-
 tests/org/easymock/tests/UsageVarargTest.java      |  342 +-
 tests/org/easymock/tests/UsageVerifyTest.java      |  305 +-
 tests/org/easymock/tests/Util.java                 |   55 +-
 tests/org/easymock/tests2/AnswerTest.java          |  320 +-
 .../easymock/tests2/CallbackAndArgumentsTest.java  |  186 +-
 tests/org/easymock/tests2/CallbackTest.java        |  188 +-
 tests/org/easymock/tests2/CaptureTest.java         |  506 ++-
 tests/org/easymock/tests2/ChildEquals.java         |   25 +
 .../easymock/tests2/ClassExtensionHelperTest.java  |  118 +
 tests/org/easymock/tests2/CompareToTest.java       |  172 +-
 .../easymock/tests2/ConstraintsToStringTest.java   |  326 +-
 tests/org/easymock/tests2/ConstructorArgsTest.java |   91 +
 tests/org/easymock/tests2/DelegateToTest.java      |  138 +
 tests/org/easymock/tests2/DependencyTest.java      |   74 +
 .../tests2/EasyMockClassExtensionTest.java         |  384 ++
 .../easymock/tests2/EasyMockPropertiesTest.java    |  256 ++
 tests/org/easymock/tests2/EasyMockRunnerTest.java  |  112 +
 .../easymock/tests2/EasyMockSupportClassTest.java  |  206 ++
 tests/org/easymock/tests2/EasyMockSupportTest.java |  273 ++
 tests/org/easymock/tests2/FilteringRule.java       |  165 +
 tests/org/easymock/tests2/MockBuilderTest.java     |  355 ++
 tests/org/easymock/tests2/MockedExceptionTest.java |  122 +
 tests/org/easymock/tests2/MocksControlTest.java    |  199 +
 tests/org/easymock/tests2/NameTest.java            |  171 +-
 tests/org/easymock/tests2/NiceMockTest.java        |  108 +-
 tests/org/easymock/tests2/ParentEquals.java        |   25 +
 tests/org/easymock/tests2/PartialMockingTest.java  |   93 +
 tests/org/easymock/tests2/ReflectionUtilsTest.java |  169 +
 tests/org/easymock/tests2/SerializationTest.java   |  174 +-
 tests/org/easymock/tests2/StubTest.java            |  158 +-
 tests/org/easymock/tests2/ThreadingTest.java       |  295 +-
 .../org/easymock/tests2/UsageConstraintsTest.java  | 1294 +++----
 tests/org/easymock/tests2/UsageMatchersTest.java   |   58 +-
 tests/org/easymock/tests2/UsageStrictMockTest.java |  408 ++-
 tests/org/easymock/tests2/UsageTest.java           |  617 ++--
 190 files changed, 24654 insertions(+), 15505 deletions(-)

diff --git a/Documentation.html b/Documentation.html
index 640acfa..193ae2b 100644
--- a/Documentation.html
+++ b/Documentation.html
@@ -1,993 +1,1186 @@
-<?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 2.4 Readme</title>
-<link rel="stylesheet" href="easymock.css" />
-</head>
-<body><div class="bodywidth">
-
-<h2>EasyMock 2.4 Readme</h2>
- 
-<p>Documentation for release 2.4 (July 2 2008)<br />
-© 2001-2008 <a href="http://www.offis.de" title="OFFIS">OFFIS</a>, <a href="http://tammofreese.de" id="id" title="Tammo Freese">Tammo Freese</a>.
-</p>
-<p>
-EasyMock 2 is a library that provides an easy way to use Mock Objects for given
-interfaces. EasyMock 2 is available under the terms of the <a href="License.html">MIT 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 2 generates Mock Objects
-dynamically - no need to write them, and no generated code!
-</p>
-<h3>
-EasyMock 2 Benefits
-</h3>
-<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>
-<h3>EasyMock 2 Drawbacks
-</h3>
-<ul>
-<li>EasyMock 2 does only work with Java 2 Version 5.0 and above.
-</li>
-</ul>
-<p>
-EasyMock by default supports the generation of Mock Objects
-for interfaces only. For those who would like to generate
-Mock Objects for classes, there is an extension
-available at the EasyMock home page.
-</p>
-<h2>
-Installation
-</h2>
-<ol>
-<li>Java 2 (at least 5.0) is required.
-</li>
-<li>Unzip the EasyMock zip file (<code>easymock2.4.zip</code>). It contains a directory
-<code>easymock2.4</code>. Add the EasyMock jar file (<code>easymock.jar</code>) from this directory to your
-classpath.
-</li>
-</ol>
-<p>
-To execute the EasyMock tests, add <code>tests.zip</code> and the JUnit 4.1 jar 
-to your class path and start
-<code>'java org.easymock.tests.AllTests'</code>.
-</p>
-<p>
-The source code of EasyMock is stored in the zip file <code>src.zip</code>.
-</p>
-<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>samples.zip</code>.
-</p>
-<p>
-The following examples assume that you are familiar with the JUnit testing framework.
-Although the tests shown here use JUnit in version 3.8.1, you may as well use JUnit 4 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>samples.zip</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 junit.framework.TestCase;
-
-public class ExampleTest extends TestCase {
-
-    private ClassUnderTest classUnderTest;
-    private Collaborator mock;
-
-    protected void setUp() {
-        classUnderTest = new ClassUnderTest();
-        classUnderTest.addListener(mock);
-    }
-
-    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 2, 
-we only need a static import of methods of <code>org.easymock.EasyMock</code>.
-This is the only non-internal, non-deprecated class of EasyMock 2. 
-</p>
-<pre>
-import static org.easymock.EasyMock.*;
-import junit.framework.TestCase;
-
-public class ExampleTest extends TestCase {
-
-    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>
-    protected void setUp() {
-        mock = createMock(Collaborator.class); // 1
-        classUnderTest = new ClassUnderTest();
-        classUnderTest.addListener(mock);
-    }
-
-    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>
-    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: 1 (+1)
-    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>
-    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>
-    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>
-    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: 3 (+1)
-	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>
-    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);
-    }
-
-    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>
-<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>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></dt>
-<dd>Matches if the actual value is null. Available for objects.</dd>
-
-<dt><code>notNull()</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></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.</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 three object methods <code>equals()</code>,
-<code>hashCode()</code> and <code>toString()</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>
-By default, mocks are not thread-safe. They also checks that they are indeed used in 
-only one thread. To synchronize it, call the <code>makeThreadSafe</code> method. Note
-that all mocks create with a given <code>IMocksControl</code> will be synchronized with one another.
-</p>
-<h3>Backward Compatibility</h3>
-<p>
-EasyMock 2 contains a compatibility layer so that tests using EasyMock 1.2 for Java 1.5
-should work without any modification. The only known differences are visible when 
-failures occur: there are small changes in the failure messages and stack traces,
-and failures are now reported using Java's <code>AssertionError</code> instead of
-JUnit's <code>AssertionFailedError</code>.
-</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>
-<h2>
-EasyMock Development
-</h2>
-<p>
-EasyMock 1.0 has been developed by Tammo Freese at OFFIS.
-The development of EasyMock is now hosted on SourceForge
-to allow other developers and companies to contribute.
-</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, Henri Tremblay, Bill Uetrecht,
-Frank Westphal, Chad Woolley, Bernd Worsch, 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 at yahoogroups.com?subject=EasyMock 2.4 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 at yahoogroups.com">easymock-subscribe at yahoogroups.com</a>.
-</p>
-<h3>
-EasyMock Version 2.4 (July 2 2008) Release Notes
-</h3>
-<p>
-Changes since 2.3:
-</p>
-<ul>
-<li>Be able to capture an argument passed to a mock (1963449)
-</li>
-<li>Add resetToNice/Default/Strict methods (1963442)
-</li>
-<li>Make generic comparator more flexible
-</li>
-<li>Mocks are now serializable (1895630)
-</li>
-<li>Can now resume after an ignored failure (1896509)
-</li>
-<li>Can make a mock thread-safe (1895644,1953275)
-</li>
-<li>Check that an unsafe mock isn't used in a multithreaded environment 
-</li>
-</ul>
-<p>
-Changes since 2.2:
-</p>
-<ul>
-<li>French documentation
-</li>
-<li>Matchers for Comparable parameters 
-</li>
-<li>Decimal comparison fix
-</li>
-<li>Mock Objects can now be named 
-</li>
-<li>Include Bill Michell's ThreadLocal fix
-</li>
-<li>Converted EasyMock's unit tests to JUnit 4
-</li>
-</ul>
-<p>
-Changes since 2.1:
-</p>
-<ul>
-<li>answers for expected calls can now be created at call time via
-<code>andAnswer(IAnswer answer)</code> and <code>andStubAnswer(IAnswer answer)</code>
-</li>
-<li><code>callback(Runnable runnable)</code> has been removed, for callbacks, please 
-switch to  
-<code>andAnswer(IAnswer answer)</code> and <code>andStubAnswer(IAnswer answer)</code>
-</li>
-<li><code>replay()</code>, <code>verify()</code> and <code>reset()</code> now accept
-multiple mock objects as arguments
-</li>
-</ul>
-<p>
-Changes since 2.0:
-</p>
-<ul>
-<li>arguments passed to the mock object are now available in callbacks via
-<code>EasyMock.getCurrentArguments()</code>
-</li>
-<li>fixed bug reported in http://groups.yahoo.com/group/easymock/message/558
-</li>
-<li>earlier failing if unused matchers were specified
-</li>
-</ul>
-<p>
-Changes since 1.2:
-</p>
-<ul>
-<li>support for flexible, refactoring-safe argument matchers
-</li>
-<li>no mock control is needed for single Mock Objects
-</li>
-<li>stub behavior replaces default behavior
-</li>
-<li>support for call order checking for more than one mock, and to switch order checking on and off
-</li>
-<li>support for callbacks
-</li>
-<li>EasyMock now throws <code>java.lang.AssertionError</code> instead of <code>junit.framework.AssertionFailedError</code>
-so that it is now independent from the testing framework, you may use it with JUnit 3.8.x, JUnit 4 and TestNG
-</li>
-<li>deprecated old API
-</li>
-</ul>
-</div>
-</body>
-</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.2 Readme</title>
+<link rel="stylesheet" href="easymock.css" />
+</head>
+<body><div class="bodywidth">
+
+<h2>EasyMock 3.2 Readme</h2>
+ 
+<p>Documentation for release 3.2 (2013-07-11)<br />
+© 2001-2013 <a href="http://www.offis.de">OFFIS</a>, <a href="http://tammofreese.de">Tammo Freese</a>, <a href="http://henritremblay.blogspot.fr/">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.2</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.2.zip</code>).</li>
+<li>Go into the <code>easymock-3.2</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.2-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.2-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 {
+
+    private Collaborator listener;
+    // ...
+    public void setListener(Collaborator listener) {
+        this.listener = 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.2-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.2-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.setListener(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.setListener(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>
+    Using annotations
+</h3>
+<p>
+Since EasyMock 3.2, it is now possible to create mocks using annotations. This is a nice and shorter way to create your
+mocks and inject them to the tested class. Here is the example above, now using annotations:
+</p>
+<pre>
+import static org.easymock.EasyMock.*;
+
+import org.easymock.EasyMockRunner;
+import org.easymock.TestSubject;
+import org.easymock.Mock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+ at RunWith(EasyMockRunner.class)
+public class ExampleTest {
+
+    @TestSubject
+    private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2
+
+    @Mock
+    private Collaborator mock; // 1
+
+    @Test
+    public void testRemoveNonExistingDocument() {
+        replay(mock);
+        classUnderTest.removeDocument("Does not exist");
+    }
+}
+</pre>
+<p>
+The <code>mock</code> is instantiated by the runner at step 1. It is then set by the runner, to the <code>listener</code>
+field on step 2. The <code>setUp</code> method can be removed since all the initialisation was done by the runner.
+</p>
+<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>, <code>anyString()</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 two ways.
+</p>
+<ul>
+<li>In an <code>easymock.properties</code> file set in the classpath default package 
+</li>
+<li>By calling <code>EasyMock.setEasyMockProperty</code>. Constants are available 
+in the <code>EasyMock</code> class. Setting properties in the code obviously override any property set
+in <code>easymock.properties</code>
+</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>
+<h3>Android support</h3>
+<p>
+Since EasyMock 3.2, EasyMock can be used on Android VM (Dalvik). Just add a dependency to you apk project used to test 
+your application. It is a good idea to exclude cglib since dexmaker is used instead. You should also add dexmaker
+explicitly because it's an optional dependency. If you use Maven, the final required dependencies will look like this
+</p>
+<pre>
+<dependency>
+  <groupId>org.easymock</groupId>
+  <artifactId>easymock</artifactId>
+  <version>3.2</version>
+  <exclusions>
+    <exclusion>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+    </exclusion>
+  </exclusions>
+</dependency>
+<dependency>
+  <groupId>com.google.dexmaker</groupId>
+  <artifactId>dexmaker</artifactId>
+  <version>1.0</version>
+</dependency>    
+</pre>   
+<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 at 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 at yahoogroups.com">easymock-subscribe at yahoogroups.com</a>.
+</p>
+</div>
+</body>
+</html>
diff --git a/Documentation_fr.html b/Documentation_fr.html
index 1de704f..2494d97 100644
--- a/Documentation_fr.html
+++ b/Documentation_fr.html
@@ -1,1042 +1,1251 @@
-<?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="fr">
-
-<head>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />	
-<title>EasyMock 2.4 Readme</title>
-<link rel="stylesheet" href="easymock.css" />
-</head>
-<body><div class="bodywidth">
-
-<h2>EasyMock 2.4 Readme</h2>
- 
-<p>Documentation de la version 2.4 (July 2 2008)<br />
-© 2001-2008 <a href="http://www.offis.de" title="OFFIS">OFFIS</a>, <a href="http://tammofreese.de" id="id" title="Tammo Freese">Tammo Freese</a>.
-</p>
-<p>Traduit originellement de l'anglais par <a href="http://alexdp.free.fr">Alexandre de Pellegrin</a>.
-Maintenue par Henri Tremblay.
-</p>
-<p>
-EasyMock 2 est une librairie fournissant un moyen simple d'utiliser des Mock Objects pour
-une interface donnée. EasyMock 2 est disponible sous <a href="License.html">licence MIT</a>.
-</p>
-<p>
-Les Mock Objects simulent le comportement du code
-métier et sont capables de vérifier s'il est utilisé
-comme prévu.
-Les classes métier peuvent être testées
-de façon isolée en simulant leurs objets
-liés par des Mock Objects.
-</p>
-<p>
-Ecrire et maintenir des Mock Objects est souvent une
-tâche pénible et source d'erreurs. EasyMock 2
-génère les
-Mock Objects dynamiquement - pas besoin de les écrire, pas
-de code généré!
-</p>
-<h3>
-Avantages d'EasyMock 2
-</h3>
-<ul>
-<li>Pas d'écriture manuelle des Mock Objects.
-</li>
-<li>Supporte le refactoring sur les Mock Objects : le code de test ne sera pas cassé au runtime lors du renommage de
-    méthodes ou de la réorganisations de paramètres
-</li>
-<li>Supporte les valeurs de retour et les exceptions.
-</li>
-<li>Supporte la vérification de l'ordre d'appel des méthodes, sur un ou plusieurs Mock Objects.
-</li>
-</ul>
-<h3>Inconvénients d'EasyMock 2
-</h3>
-<ul>
-<li>EasyMock 2 fonctionne uniquement avec Java 2 Version 5.0 ou version supérieure.
-</li>
-</ul>
-<p>
-Par défaut, EasyMock supporte la génération de
-Mock Objects uniquement pour les interfaces. Pour ceux souhaitant
-générer des Mock Objects pour des 
-classes, il existe une extension disponible sur la page d'accueil d'EasyMock.
-</p>
-<h2>
-Installation
-</h2>
-<ol>
-<li>Java 2 (minimum 5.0) est requis.
-</li>
-<li>Décompressez le fichier zip d'EasyMock (<code>easymock2.4.zip</code>). Il contient le répertoire
-<code>easymock2.4</code>. Ajoutez le jar d'EasyMock (<code>easymock.jar</code>) de ce répertoire dans votre 
-classpath.
-</li>
-</ol>
-<p>
-Pour exécuter les tests d'EasyMock, ajoutez <code>tests.zip</code> et le jar de JUnit 4.1
-à votre classpath and lancez 
-<code>'java org.easymock.tests.AllTests'</code>.
-</p>
-<p>
-Le code source d'EasyMock est situé dans <code>src.zip</code>.
-</p>
-<h2>
-Utilisation
-</h2>
-<p>
-La plupart des éléments d'un logiciel ne fonctionnent
-pas de manière isolée mais en collaboration avec
-d'autres éléments (objets liés) pour effectuer leur
-tâche.
-Dans beaucoup de cas, nous ne nous soucions pas d'utiliser des objets
-liés pour nos tests unitaires du moment
-que nous avons confiance en eux. Si
-ce n'est pas le cas, les Mock Objects peuvent nous aider à
-tester unitairement de façon isolée. Les Mock Objects
-remplacent les objets liés de l'élément testé.
-</p>
-<p>
-Les exemples suivants utilisent l'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>
-Les implémentations de cette interface sont des
-objets liés (des listeners dans ce cas) à la classe nommée <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>
-Le code de la classe et de l'interface est disponible dans
-le package
-<code>org.easymock.samples</code> dans <code>samples.zip</code>.
-</p>
-<p>
-Les exemples qui suivent supposent que vous êtes familier avec le framework de test JUnit.
-Bien que les tests montrés ici utilisent JUnit version 3.8.1, vous pouvez également utiliser JUnit 4 ou TestNG.
-</p>
-<h3>
-Votre premier Mock Object
-</h3>
-<p>
-Nous allons maintenant construire un cas de test et jouer avec pour
-comprendre les fonctionnalités du package EasyMock. Le
-fichier <code>samples.zip</code> contient une version modifiée de ce test. 
-Notre premier test devra vérifier que la suppression d'un document non existant <strong>ne doit pas</strong>
-provoquer la notification de l'objet lié. Voici le test dans la définition du Mock Object:
-</p>
-<pre>
-package org.easymock.samples;
-
-import junit.framework.TestCase;
-
-public class ExampleTest extends TestCase {
-
-    private ClassUnderTest classUnderTest;
-    private Collaborator mock;
-
-    protected void setUp() {
-        classUnderTest = new ClassUnderTest();
-        classUnderTest.addListener(mock);
-    }
-
-    public void testRemoveNonExistingDocument() {    
-        // This call should not lead to any notification
-        // of the Mock Object: 
-        classUnderTest.removeDocument("Does not exist");
-    }
-}
-</pre>
-<p>
-Pour beaucoup de tests utilisant EasyMock 2, nous avons
-uniquement besoin de l'import statique des méthodes de la classe
-<code>org.easymock.EasyMock</code>.
-Cette classe est la seule non interne et non dépréciée d'EasyMock 2.
-</p>
-<pre>
-import static org.easymock.EasyMock.*;
-import junit.framework.TestCase;
-
-public class ExampleTest extends TestCase {
-
-    private ClassUnderTest classUnderTest;
-    private Collaborator mock;
-    
-}    
-</pre>
-<p>
-Pour obtenir un Mock Object, il faut:
-</p>
-<ol>
-<li>créer un Mock Object pour l'interface à simuler,
-</li>
-<li>enregistrer le comportement attendu, puis
-</li>
-<li>basculer le Mock Object à l'état 'replay'.
-</li>
-</ol>
-<p>
-Voici le premier exemple:
-</p>
-<pre>
-    protected void setUp() {
-        mock = createMock(Collaborator.class); // 1
-        classUnderTest = new ClassUnderTest();
-        classUnderTest.addListener(mock);
-    }
-
-    public void testRemoveNonExistingDocument() {
-        // 2 (we do not expect anything)
-        replay(mock); // 3
-        classUnderTest.removeDocument("Does not exist");
-    }
-</pre>
-<p>
-Après activation à l'étape 3, <code>mock</code> 
-est un Mock Object de l'interface <code>Collaborator</code>
-qui n'attend aucun appel. Cela signifie que si nous changeons notre <code>ClassUnderTest</code> 
-pour appeler n'importe quelle méthode de l'interface, le Mock Object lévera 
-une <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>
-   Ajouter un comportement
-</h3>
-<p>
-Écrivons un second test. Si un document est ajouté à
-la classe testée, nous nous attendons à un appel à
-<code>mock.documentAdded()</code>
-sur le Mock Object avec le titre du document en argument:
-</p>
-<pre>
-    public void testAddDocument() {
-        mock.documentAdded("New Document"); // 2
-        replay(mock); // 3
-        classUnderTest.addDocument("New Document", new byte[0]); 
-    }
-</pre>
-<p>
-Aussi, dans l'étape d'enregistrement (avant d'appeler <code>replay</code>),
-le Mock Object ne se comporte pas comme<em></em> un Mock Object mais enregistre 
-les appels de méthode. Après l'appel à <code>replay</code>,
-il se comporte comme un Mock Object, vérifiant que les appels 
-de méthode attendus ont bien lieu.
-</p>
-<p>
-Si <code>classUnderTest.addDocument("New Document", new byte[0])</code>
-appelle la méthode attendue avec un mauvais argument, le
-Mock Object lèvera une <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>
-Tous les appels attendus n'ayant pas eu lieu sont montrés, ainsi
-que tous les appels faits alors qu'ils étaient non attendus
-(aucun dans notre cas). Si l'appel à la méthode est
-effectué trop de fois, le Mock Object le signale
-également:
-</p>
-<pre>
-java.lang.AssertionError: 
-  Unexpected method call documentAdded("New Document"):
-    documentAdded("New Document"): expected: 1, actual: 1 (+1)
-    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>
-Vérifier le comportement
-</h3>
-<p>
-Il y a un type d'erreur dont nous ne nous sommes pas
-préoccupés jusqu'à présent: si nous décrivons un
-comportement, nous voulons vérifier qu'il est bien respecté. 
-Le test qui suit passe si une méthode du Mock Object est appelée. 
-Pour vérifier cela, nous devons appeler <code>verify(mock)</code>:
-</p>
-<pre>
-    public void testAddDocument() {
-        mock.documentAdded("New Document"); // 2 
-        replay(mock); // 3
-        classUnderTest.addDocument("New Document", new byte[0]);
-        verify(mock);
-    }
-</pre>
-<p>
-Si la méthode du Mock Object n'est pas appelée, 
-l'exception suivante sera levée :
-</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>
-Le message de l'exception liste tous les appels attendus qui n'ont pas eu lieu.
-</p>
-<h3>
-Attendre un nombre explicite d'appels
-</h3>
-<p>
-Jusqu'à maintenant, nos tests ont été faits uniquement
-sur un seul appel de méthode. Le test suivant
-vérifiera que l'ajout d'un document déjà existant
-déclenche l'appel à <code>mock.documentChanged()</code>
-avec l'argument approprié. Pour en être certain, nous
-vérifions cela trois fois (après tout, c'est un exemple
-;-)):
-</p>
-<pre>
-    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>
-Afin d'éviter la répétition de  <code>mock.documentChanged("Document")</code>,
-EasyMock fournit un raccourci. Nous pouvons spécifier le nombre d'appel avec la méthode
-<code>times(int times)</code> sur l'objet retourné par <code>expectLastCall()</code>.
-Le code ressemble alors à cela:
-</p>
-<pre>
-    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>
-Si la méthode est appelée un trop grand nombre de fois,
-une exception sera levée nous indiquant que la méthode a
-été appelée trop de fois.
-L'erreur est levée immédiatement après le premier
-appel dépassant la limite:
-</p>
-<pre>
-java.lang.AssertionError: 
-  Unexpected method call documentChanged("Document"):
-    documentChanged("Document"): expected: 3, actual: 3 (+1)
-	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>
-S'il y a trop peu d'appels, <code>verify(mock)</code>
-lève une <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>
-Spécifier des valeurs de retour
-</h3>
-<p>
-Pour spécifier des valeurs de retour, nous encapsulons l'appel attendu dans
-<code>expect(T value)</code> et spécifions la valeur de retour avec la 
-méthode <code>andReturn(Object returnValue)</code> sur l'objet retourné par
-<code>expect(T value)</code>.
-</p>
-<p>
-Prenons par exemple la vérification du workflow lors de la suppresion d'un document. 
-Si <code>ClassUnderTest</code> fait un appel pour supprimer un document, 
-il doit demander aux objets liés de voter pour cette suppression 
-par appel à <code>byte voteForRemoval(String title)</code>.
-Une réponse positive approuve la suppression. Si la somme de
-toutes les réponses est positive, alors le document est
-supprimé et l'appel à <code>documentRemoved(String title)</code> 
-est effectué sur les objets liés:
-</p>
-<pre>
-    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);
-    }
-
-    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>
-Le type de la valeur de retour est vérifié à la
-compilation. Par exemple, le code suivant ne compilera pas du fait que
-le type fourni ne correspond au type retourné par la
-méthode:
-</p>
-<pre>
-    expect(mock.voteForRemoval("Document")).andReturn("wrong type");
-</pre>
-<p>
-Au lieu d'appeler <code>expect(T value)</code> pour
-récuperer l'objet auquel affecter une valeur de retour, 
-nous pouvons aussi utiliser l'objet retourné par <code>expectLastCall()</code>.
-Ainsi, au lieu de 
-</p>
-<pre>
-    expect(mock.voteForRemoval("Document")).andReturn((byte) 42);
-</pre>
-<p>
-nous pouvons écrire
-</p>
-<pre>
-    mock.voteForRemoval("Document");
-    expectLastCall().andReturn((byte) 42);
-</pre>
-<p>
-Ce type d'écriture doit uniquement être utilisé
-si la ligne est trop longue car il n'inclut pas la vérification
-du type à la compilation.
-</p>
-<h3>
-Travailler avec les exceptions
-</h3>
-<p>
-Afin de spécifier les exceptions (plus précisemment:
-les Throwables) devant être levées, l'objet
-retourné par <code>expectLastCall()</code> et <code>expect(T value)</code> 
-fournit la méthode <code>andThrow(Throwable throwable)</code>.
-Cette méthode doit être appelée durant l'étape
-d'enregistrement après l'appel au Mock Object pour lequel le <code>Throwable</code>
-doit être levé.
-</p>
-<p>
-Les exception non "checkées" (comme <code>RuntimeException</code>,
-<code>Error</code> ainsi que toutes leurs sous classes) peuvent
-être levées de n'importe quelle méthode. Les
-exceptions "checkées" ne doivent être levées que 
-pour methodes où cela est prévu.
-</p>
-<h3>
-Créer des valeurs de retour ou des exceptions
-</h3>
-<p>
-Parfois, nous voulons que notre Mock Object retourne une valeur ou
-lève une exception créée au moment de l'appel.
-Depuis la version 2.2 d'EasyMock, l'objet retourné 
-par <code>expectLastCall()</code> et <code>expect(T value)</code> fournit la méthode
-<code>andAnswer(IAnswer answer)</code> permettant de spécifier une implémentation 
-de l'interface <code>IAnswer</code> utilisée pour créer 
-une valeur de retour ou une exception.
-</p>
-<p>
-Au sein d'<code>IAnswer</code>, les arguments passés lors de l'appel au mock sont 
-disponibles via <code>EasyMock.getCurrentArguments()</code>.
-Si vous utilisez cela, les refactorings du type réorganisation
-de l'ordre des arguments brisseront vos tests. Vous êtes prévenu.
-</p>
-<h3>
-Changer de comportement sur le même appel de méthode
-</h3>
-<p>
-Il est également possible de spécifier un changement de comportement pour une méthode.
-Les méthodes <code>times</code>, <code>andReturn</code> et <code>andThrow</code>
-peuvent être chaînées. Comme exemple, 
-nous définissons <code>voteForRemoval("Document")</code> pour
-</p>
-<ul>
-<li>retourner 42 pour les trois premiers appels,
-</li>
-<li>lever une <code>RuntimeException</code> sur le quatrième appel,
-</li>
-<li>renvoyer -42 une fois.
-</li>
-</ul>
-<pre>
-    expect(mock.voteForRemoval("Document"))
-        .andReturn((byte) 42).times(3)
-        .andThrow(new RuntimeException(), 4)
-        .andReturn((byte) -42);
-</pre>
-<h3>
-Être plus permissif sur le nombre d'appels
-</h3>
-<p>
-Afin d'être plus permissif sur le nombre d'appels attendus,
-des méthodes additionnelles peuvent être
-utilisées à la place de <code>times(int count)</code>:
-</p>
-<dl>
-<dt><code>times(int min, int max)</code></dt> 
-<dd>pour attendre entre <code>min</code> and <code>max</code> appels,</dd>
-<dt><code>atLeastOnce()</code></dt>
-<dd>pour attendre au moins un appel, et</dd>
-<dt><code>anyTimes()</code></dt>
-<dd>pour attendre une quantité non définie d'appels.</dd>
-</dl>
-<p>
-Si aucun nombre d'appels n'est explicitement défini,
-alors seul un appel est attendu. Pour le définir explicitement,
-vous pouvez utiliser <code>once()</code> ou <code>times(1)</code>.
-</p>
-<h3>
-Mocks stricts
-</h3>
-<p>
-Sur un Mock Object retourné par <code>EasyMock.createMock()</code>,
-l'ordre d'appel des méthodes n'est pas vérifié.
-Si vous souhaitez avoir un Mock Object 'strict' vérifiant cet ordre,
-utilisez <code>EasyMock.create<i>Strict</i>Mock()</code>.</p>
-<p>
-Lorsqu'un appel inattendu à une méthode est fait sur
-un Mock Object 'strict', le message de l'exception contient les appels 
-de méthode attendus à ce moment, suivi du premier appel en
-conflit. <code>verify(mock)</code> montre tous les appels de méthode manqués.
-</p>
-<h3>
-Activer/Désactiver la vérification de l'ordre d'appel des méthodes
-</h3>
-<p>
-Il est parfois nécessaire qu'un Mock Object vérifie
-l'ordre d'appel sur certains appels uniquement. Pendant la phase
-d'enregistrement, vous pouvez activer la vérification de l'ordre
-d'appel en utilisant <code>checkOrder(mock, true)</code> et la 
-désactiver en utilisant <code>checkOrder(mock, false)</code>.
-</p>
-<p>
-Il y a deux différences entre un Mock Object 'strict' et un Mock Object 'normal':
-</p>
-<ol>
-	<li> Un mock 'strict' à la vérification de l'order d'appel activé à la cré. </li>
-	<li> Un mock 'strict' à la vérification de l'order d'appel activé ès reset (voir <em>Réutilisation d'un Mock Object</em>). </li>
-</ol>
-<h3>
-Définir des comparateurs d'arguments pour plus de souplesse
-</h3>
-<p>
-Pour vérifier la correspondance à un appel de méthode prévu sur un Mock Object, 
-les arguments<code> de type Object</code> sont comparés, par défaut, avec
-<code>equals()</code>. Cela peut introduire des problèmes. Considérons l'exemple suivant:
-</p>
-<pre>
-String[] documents = new String[] { "Document 1", "Document 2" };
-expect(mock.voteForRemovals(documents)).andReturn(42);
-</pre>
-<p>
-Si la méthode est appelée avec un autre tableau ayant le même contenu,
-cela provoque une exception du fait que <code>equals()</code> compare l'identité 
-des objets pour les tableaux:
-</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>
-Pour spécifier que seule l'égalité de tableau
-est nécessaire pour cet appel, utilisez la méthode 
-<code>aryEq</code>, importée statiquement de la classe <code>EasyMock</code>:
-</p>
-<pre>
-String[] documents = new String[] { "Document 1", "Document 2" };
-expect(mock.voteForRemovals(aryEq(documents))).andReturn(42);
-</pre>
-<p>
-Si vous souhaitez utiliser les comparateurs lors d'un appel, vous devez
-en utiliser pour chaque argument de la méthode appelée.
-</p>
-<p>
-Voici quelques comparateurs prédéfinis disponible:
-</p>
-<dl>
-
-<dt><code>eq(X value)</code></dt>
-<dd>Vérifie que la valeur reçue égale la valeur attendue. Disponible pour tous les types primitifs et objets.</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>anyShort()</code></dt>
-<dd>Laisse passer n'importe quelle valeur. Disponible pour tous les types primitifs et objets.</dd>
-
-<dt><code>eq(X value, X delta)</code></dt>
-<dd>Vérifie que la valeur recçue égale la valeur attendue, plus ou moins un delta. Disponible pour les <code>float</code> et <code>double</code>.</dd>
-
-<dt><code>aryEq(X value)</code></dt>
-<dd>Vérifie que la valeur recçue égale la valeur attendue en s'appuyant sur <code>Arrays.equals()</code>. Disponible pour les tableaux d'objets et de types primitifs.</dd>
-
-<dt><code>isNull()</code></dt>
-<dd>Vérifie que la valeur reçue est nulle. Disponible pour les objets.</dd>
-
-<dt><code>notNull()</code></dt>
-<dd>Vérifie que la valeur reçue n'est pas nulle. Disponible pour les objets.</dd>
-
-<dt><code>same(X value)</code></dt>
-<dd>Vérifie que la valeur reçue est la même que la value attendue. Disponible pour les objets.</dd>
-
-<dt><code>isA(Class clazz)</code></dt>
-<dd>Vérifie que la valeur reçue est une instance de clazz ou d'une classe hérite ou implémente clazz. Disponible pour les objets.</dd>
-
-<dt><code>lt(X value)</code>, <code>leq(X value)</code>, <code>geq(X value)</code>, <code>gt(X value)</code></dt>
-<dd>Vérifie que la valeur reçue est inférieure/inférieure ou égale/supérieure
-ou égale/supérieure à la valeur attendue. Disponible pour tous les types primitifs numériques et les implémentations de <code>Comparable</code>.</dd>
-
-<dt><code>startsWith(String prefix), contains(String substring), endsWith(String suffix)</code></dt>
-<dd>Vérifie que la valeur reçue commence par/contient/se termine par la valeur attendue. Disponible pour les <code>String</code>s.</dd>
-
-<dt><code>matches(String regex), find(String regex)</code></dt>
-<dd>Vérifie que la valeur reçue/une sous-chaîne de la valeur reçue correspond à l'expression ré. Disponible pour les <code>String</code>s.</dd>
-
-<dt><code>and(X first, X second)</code></dt>
-<dd>Est valide si les résultats des deux comparateurs utilisés en <code>first</code> et <code>second</code> sont vérifiés. Disponible pour tous les types primitifs et objets.</dd>
-
-<dt><code>or(X first, X second)</code></dt>
-<dd>Est valide si l'un des résultats des deux comparateurs utilisés en <code>first</code> et <code>second</code> est vérifié. Disponible pour tous les types primitifs et objets.</dd>
-
-<dt><code>not(X value)</code></dt>
-<dd>Est valide si le résultat du comparateur utilisé dans <code>value</code> est négatif.</dd>
-
-<dt><code>cmpEq(X value)</code></dt>
-<dd>Vérifie que la valeur reçue égale la valeur attendue du point de vue de <code>Comparable.compareTo(X o)</code>. Disponible pour tous les types primitifs numériques et les implémentations de <code>Comparable</code>.</dd>
-
-<dt><code>cmp(X value, Comparator<X> comparator, LogicalOperator operator)</code></dt>
-<dd>Vérifie que <code>comparator.compare(reçue, value) operator 0</code> où <code>operator</code> est <,<=,>,>= ou ==.</dd>
-
-<dt><code>capture(Capture<T> capture)</code></dt>
-<dd>Laisse passer n'importe quelle valeur mais la capture dans le paramètre <code>Capture</code> pour un usage ultérieurs. Vous pouvez utiliser <code>and(someMatcher(...), capture(c))</code> pour 
-capturer un paramètre d'un appel de méthode en particulier.</dd>
-
-</dl>
-
-<h3>
-Définir son propre comparateur d'arguments
-</h3>
-<p>
-Il peut être intéressant de définir son propre
-comparateur d'argument. Prenons un comparateur dont le rôle
-serait de vérifier une exception par rapport à son
-type et message. Il pourrait être utilisé de la façon suivante:
-</p>
-<pre>
-    IllegalStateException e = new IllegalStateException("Operation not allowed.")
-    expect(mock.logThrowable(eqException(e))).andReturn(true);
-</pre>
-<p>
-Deux étapes sont nécessaires pour réaliser cela: le nouveau comparateur
-doit être défini et la méthode statique <code>eqException</code> 
-doit être déclarée.
-</p>
-<p>
-Pour définir le nouveau comparateur d'argument, nous implémentons l'interface <code>org.easymock.IArgumentMatcher</code>.
-Cette interface contient deux méthodes: <code>matches(Object actual)</code>, vérifiant 
-que l'argument reçu est bien celui attendu, et <code>appendTo(StringBuffer buffer)</code>,
-ajoutant au StringBuffer une chaine de caractères représentative du comparateur d'argument.
-L'implémentation est la suivante :
-</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>
-La méthode <code>eqException</code> doit instancier le
-comparateur d'argument avec l'objet Throwable donné, le fournir
-à EasyMock via la méthode statique <code>reportMatcher(IArgumentMatcher matcher)</code>
-et retourner une valeur afin d'être utilisée au sein de l'appel à la méthode mockée 
-(typiquement <code>0</code>, <code>null</code> ou <code>false</code>). Une première tentative ressemblerait à ceci:
-</p>
-<pre>
-public static Throwable eqException(Throwable in) {
-    EasyMock.reportMatcher(new ThrowableEquals(in));
-    return null;
-}
-</pre>
-<p>
-Cependant, cela ne fonctionnerait que si la méthode <code>logThrowable</code>
-de l'exemple acceptait <code>Throwable</code>s et quelque chose de plus spécifique du style de <code>RuntimeException</code>. 
-Dans ce dernier cas, le code de notre exemple ne compilerait pas:
-</p>
-<pre>
-    IllegalStateException e = new IllegalStateException("Operation not allowed.")
-    expect(mock.logThrowable(eqException(e))).andReturn(true);
-</pre>
-<p>
-Java 5.0 à la rescousse: Au lieu de définir <code>eqException</code>
-avec un <code>Throwable</code> en paramètre, nous utilisons un type générique 
-qui hérite de <code>Throwable</code>:
-</p>
-<pre>
-public static <T extends Throwable> T eqException(T in) {
-    reportMatcher(new ThrowableEquals(in));
-    return null;
-}
-</pre>
-<h3>
-Réutilisation d'un Mock Object
-</h3>
-<p>
-Les Mock Objects peuvent être réinitialisés avec <code>reset(mock)</code>.
-</p>
-<p>
-Au besoin, un Mock Object peut aussi être converti d'un type à l'autre en appelant <code>resetToNice(mock)</code>, 
-<code>resetToDefault(mock)</code> ou <code>resetToStrict(mock)</code>.
-</p>
-<h3>
-Utilisation d'un comportement de "stub" pour les méthodes
-</h3>
-<p>
-Dans certains cas, nous voudrions que nos Mock Object répondent
-à certains appels, mais sans tenir compte du nombre de fois, de l'ordre
-ni même s'ils ont été eu lieu.
-Ce comportement de "stub" peut être défini en utilisant
-les méthodes <code>andStubReturn(Object value)</code>, 
-<code>andStubThrow(Throwable throwable)</code>, <code>andStubAnswer(IAnswer<t> answer)</code>
-et <code>asStub()</code>. Le code suivant configure le Mock Object pour répondre 42 
-à <code>voteForRemoval("Document")</code> une fois et -1 pour tous les autres arguments:
-</p>
-<pre>
-    expect(mock.voteForRemoval("Document")).andReturn(42);
-    expect(mock.voteForRemoval(not(eq("Document")))).andStubReturn(-1);
-</pre>
-<h3>
-Création de mocks dits "gentils"
-</h3>
-<p>
-Pour un Mock Object retourné par <code>createMock()</code>, le comportement par défaut pour toutes 
-les méthodes est de léver une <code>AssertionError</code> pour tous les appels non prévus.
-Si vous souhaitez avoir un Mock Object "gentil" autorisant, par défaut, l'appel à 
-toutes les méthodes et retournant la valeur vide appropriée (<code>0</code>, <code>null</code>
-ou <code>false</code>), utilisez <code>create<i>Nice</i>Mock()</code> au lieu de <code>createMock()</code>.
-</p>
-
-<a id="Object_Methods"/><h3>Méthodes de la classe Object</h3>
-<p>
-Les comportements des trois méthodes <code>equals()</code>,
-<code>hashCode()</code> et <code>toString()</code>
-ne peuvent être changés sur des Mock Objects créés avec EasyMock,
-même si elles font partie de l'interface duquel le Mock Object est créé.
-</p>
-<h3>Vérifier l'ordre d'appel des méthodes entre plusieurs Mocks</h3>
-<p>
-Jusqu'à présent, nous avons vu un Mock Object comme étant
-seul et configuré par les méthodes statiques de la classe <code>EasyMock</code>. 
-Mais beaucoup de ces méthodes statiques font référence à l'objet "control"
-caché de chaque Mock Object et lui délègue l'appel. Un
-Mock Control est un objet implementant l'interface <code>IMocksControl</code>.
-</p>
-<p>
-Du coup, au lieu de
-</p>
-<pre>
-    IMyInterface mock = createStrictMock(IMyInterface.class);
-    replay(mock);
-    verify(mock); 
-    reset(mock);
-</pre>
-<p>
-nous pourrions utiliser le code équivalent:
-</p>
-<pre>
-    IMocksControl ctrl = createStrictControl();
-    IMyInterface mock = ctrl.createMock(IMyInterface.class);
-    ctrl.replay();
-    ctrl.verify(); 
-    ctrl.reset();
-</pre>
-<p>
-L'interface <code>IMocksControl</code> permet de créer plus d'un seul Mock Object. 
-Ainsi, il est possible de vérifier l'ordre d'appel des méthodes entre les mocks. 
-Par exemple, configurons deux mock objects pour l'interface <code>IMyInterface</code> pour lesquels 
-nous attendons respectivement les appels à <code>mock1.a()</code> et <code>mock2.a()</code>, 
-un nombre indéfini d'appels à <code>mock1.c()</code> et <code>mock2.c()</code>, 
-et enfin <code>mock2.b()</code> et <code>mock1.b()</code>, dans cet ordre:
-</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>Nommer un Mock Object</h3>
-<p>
-Les Mock Objects peuvent ê nommés à leur création en utilisant 
-<code>createMock(String name, Class<T> toMock)</code>,
-<code>createStrictMock(String name, Class<T> toMock)</code> ou
-<code>createNiceMock(String name, Class<T> toMock)</code>.
-Les noms seront affichés dans le message des <code>AssertionError</code>.
-</p>
-<h3>Sérializer un Mock Object</h3>
-<p>
-Un Mock Object peut être sérializé à n'importe quelle étape de son 
-existence. Il y a toutefois des contraintes évidentes:
-</p>
-<ul>
-<li>Les comparateurs d'arguments utilisés doivent être sérializable (ceux fournis avec EasyMock le sont)
-</li>
-<li>Les paramètres enregistrés doivent être sérializable
-</li>
-</ul>
-<h3>Traitement multifil</h3>
-<p>
-Par défaut, les Mock Objects ne sont pas à fil sécurisé. De plus, ils vérifient 
-qu'ils sont bien utilisés dans un seul fil. Pour les synchroniser, appellez la méthode 
-<code>makeThreadSafe</code>. Notez que les Mock Objects créés à partir du même 
-<code>IMocksControl</code> seront synchronisés l'un avec l'autre.
-</p>
-<h3>
-Compatibilité avec les anciennes versions
-</h3>
-<p>
-EasyMock 2 contient une couche de compatibilité. Ainsi, les
-tests utilisant EasyMock 1.2 en Java 1.5 fonctionneront sans aucune modification. 
-Les seules différences connues sont visibles lorsque qu'un test est en erreur: il y a de
-légers changements dans les messages d'erreur, les stack traces et les erreurs 
-sont maintenant remontées en utilisant <code>AssertionError</code> de Java 
-au lieu de <code>AssertionFailedError</code> de JUnit.
-</p>
-<p>EasyMock 2.1 introduisait une fonctionnalité de callback
-qui a été retirée dans EasyMock 2.2, car trop complexe. 
-Depuis EasyMock 2.2, l'interface <code>IAnswer</code>
-fournit la fonctionnalité de callback. 
-</p>
-<h2>
-Développement d'EasyMock
-</h2>
-<p>
-EasyMock 1.0 a été développé par Tammo Freese chef OFFIS.
-Le développement d'EasyMock est hébergé par SourceForge
-pour permettre à d'autres développeurs et sociétés d'y contribuer.
-</p>
-<p>
-Rémerciements à ceux qui nous ont fourni retour d'expérience et rustines, incluant
-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, Henri Tremblay, Bill Uetrecht,
-Frank Westphal, Chad Woolley, Bernd Worsch, et de nombreux autres.
-</p>
-<p>
-Merci de consulter la <a href="http://www.easymock.org">page d'accueil EasyMock</a> 
-pour être informé des nouvelles versions et transmettez vos bogues et suggestions à
-<a href="mailto:easymock at yahoogroups.com?subject=EasyMock 2.4 feedback">EasyMock Yahoo!Group</a> (en anglais SVP).
-Si vous souhaitez souscrire au EasyMock Yahoo!Group, envoyez un message à
-<a href="mailto:easymock-subscribe at yahoogroups.com">easymock-subscribe at yahoogroups.com</a>.
-</p>
-<h3>
-EasyMock Version 2.4 (July 2 2008), Notes de Mise à Jour
-</h3>
-<p>
-Changements depuis la version 2.3:
-</p>
-<ul>
-<li>Pouvoir capturer un argument passé à un Mock Object (1963449)
-</li>
-<li>Ajout des méthodes resetToNice/Default/Strict methods (1963442)
-</li>
-<li>Rendre les Comparators génériques plus flexibles
-</li>
-<li>Les Mock Objects sont maintenant sérializable (1895630)
-</li>
-<li>Il est maintenant possible de continuer normalement après une assertion ignorée (1896509)
-</li>
-<li>Possibilité de rendre un Mock Object à fil sécurisé (1895644,1953275)
-</li>
-<li>Vérification qu'un Mock Object non sécurisé n'est pas utilisé dans un environnement multifil 
-</li>
-</ul>
-<p>
-Changements depuis la version 2.2:
-</p>
-<ul>
-<li>Documentation en français
-</li>
-<li>Comparateurs pour arguments de type Comparable
-</li>
-<li>Correction de la comparaison de nombres décimaux
-</li>
-<li>Les Mock Objects peuvent maintenant être nommés
-</li>
-<li>Includ le fix de Bill Michell pour sur les ThreadLocals
-</li>
-<li>Migration des test unitaires d'EasyMock vers JUnit 4
-</li>
-</ul>
-<p>
-Changements depuis la version 2.1:
-</p>
-<ul>
-<li>la réponse aux appels peut ètre créée au moment de l'appel via
-<code>andAnswer(IAnswer answer)</code> et <code>andStubAnswer(IAnswer answer)</code>
-</li>
-<li><code>callback(Runnable runnable)</code> a été retiré, pour un callback, veuillez 
-convertir à
-<code>andAnswer(IAnswer answer)</code> et <code>andStubAnswer(IAnswer answer)</code>
-</li>
-<li><code>replay()</code>, <code>verify()</code> et <code>reset()</code> acceptent maintenant
-plusieurs mock objects comme arguments
-</li>
-</ul>
-<p>
-Changements depuis la version 2.0:
-</p>
-<ul>
-<li>les arguments passés à un mock object sont à disponibles dans un callback via 
-<code>EasyMock.getCurrentArguments()</code>
-</li>
-<li>Correction du bogue reporté par http://groups.yahoo.com/group/easymock/message/558
-</li>
-<li>remontée plus rapide d'une erreur si des comparateurs ne sont pas utilisés
-</li>
-</ul>
-<p>
-Changements depuis la version 1.2:
-</p>
-<ul>
-<li>support de comparateurs d'arguments souple et ré au refactoring-safe
-</li>
-<li>aucun mock control n'est nécessaire pour un Mock Object solitaire
-</li>
-<li>le comportement de "stub" remplace le comportement "défaut"
-</li>
-<li>support de la vérification d'ordre d'appels entre plusieurs mocks 
-avec possibilité d'activer/désactiver cette vérification
-</li>
-<li>support de callbacks
-</li>
-<li>EasyMock lève désormais des <code>java.lang.AssertionError</code> au lieu 
-de <code>junit.framework.AssertionFailedError</code> ce qui permet d'être indépendant 
-du framework de test. Vous pouvez l'utiliser avec JUnit 3.8.x, JUnit 4 et TestNG
-</li>
-<li>ancienne API dépréciée
-</li>
-</ul>
-</div>
-</body>
-</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="fr">
+
+<head>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />	
+<title>EasyMock 3.2 Readme</title>
+<link rel="stylesheet" href="easymock.css" />
+</head>
+<body><div class="bodywidth">
+
+<h2>EasyMock 3.2 Readme</h2>
+ 
+<p>Documentation de la version 3.2 (2013-07-11)<br />
+© 2001-2013 <a href="http://www.offis.de">OFFIS</a>, <a href="http://tammofreese.de">Tammo Freese</a>, <a href="http://henritremblay.blogspot.fr/">Henri Tremblay</a>.
+</p>
+<p><i>Documentation traduite originellement de l'anglais par <a href="http://alexdp.free.fr">Alexandre de Pellegrin</a>.
+Maintenue par Henri Tremblay.</i>
+</p>
+<p>
+EasyMock est une librairie fournissant un moyen simple d'utiliser des Mock Objects pour
+une interface ou classe donnée. EasyMock est disponible sous <a href="http://www.apache.org/licenses/LICENSE-2.0.txt">license Apache 2</a>.
+</p>
+<p>
+Les Mock Objects simulent le comportement du code
+métier et sont capables de vérifier s'il est utilisé
+comme prévu.
+Les classes métier peuvent être testées
+de façon isolée en simulant leurs objets
+liés par des Mock Objects.
+</p>
+<p>
+Écrire et maintenir des Mock Objects est souvent une
+tâche pénible et source d'erreurs. EasyMock génère les
+Mock Objects dynamiquement - pas besoin de les écrire, pas
+de code généré!
+</p>
+<h3>
+Avantages d'EasyMock
+</h3>
+<ul>
+<li>Pas d'écriture manuelle des Mock Objects.
+</li>
+<li>Supporte le refactoring sur les Mock Objects : le code de test ne sera pas cassé au runtime lors du renommage de
+    méthodes ou de la réorganisations de paramètres
+</li>
+<li>Supporte les valeurs de retour et les exceptions.
+</li>
+<li>Supporte la vérification de l'ordre d'appel des méthodes, sur un ou plusieurs Mock Objects.
+</li>
+</ul>
+<h2>
+Environnement Requis
+</h2>
+<ul>
+<li>EasyMock 2 fonctionne uniquement avec Java 1.5.0 ou supérieur.</li>
+<li>cglib (2.2) and Objenesis (1.2) doivent être présent dans le classpath pour faire du mocking de classes</li>
+</ul>
+<h2>
+Installation
+</h2>
+<h3>Avec Maven</h3>
+EasyMock est disponible dans le référentiel central de Maven. Ajoutez la dépendance 
+suivante à votre pom.xml:
+<pre>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.2</version>
+      <scope>test</scope>
+    </dependency>
+</pre>
+Vous pouvez, bien évidemment, n'importe quel outil de gestion de dépendances compatible
+avec le référentiel Maven.
+<h3>Manuellement</h3>
+<ul>
+<li>Décompressez le fichier zip d'EasyMock (<code>easymock-3.2.zip</code>).</li>
+<li>Allez dans le répertoire <code>easymock-3.2</code>.</li>
+<li>Ajoutez le jar d'EasyMock (<code>easymock.jar</code>) à votre classpath.</li>
+<li>Pour pouvoir mocker des classes, ajoutez aussi <a href="http://www.objenesis.org">Objenesis</a> et <a href="http://cglib.sourceforge.net/">Cglib</a> à votre classpath.</li>
+<li>Les tests sont dans <code>easymock-3.2-tests.jar</code> et peuvent être lancés à l'aide d'un JUnit TestRunner 
+en ayant JUnit 4.7, EasyMock, cglib et Objenesis dans votre classpath.</li>
+<li>Le code source d'EasyMock est situé dans <code>easymock-3.2-sources.jar</code>.</li>
+</ul>
+<h2>
+Utilisation
+</h2>
+<p>
+La plupart des éléments d'un logiciel ne fonctionnent
+pas de manière isolée mais en collaboration avec
+d'autres éléments (objets liés) pour effectuer leur
+tâche.
+Dans beaucoup de cas, nous ne nous soucions pas d'utiliser des objets
+liés pour nos tests unitaires du moment
+que nous avons confiance en eux. Si
+ce n'est pas le cas, les Mock Objects peuvent nous aider à
+tester unitairement de façon isolée. Les Mock Objects
+remplacent les objets liés de l'élément testé.
+</p>
+<p>
+Les exemples suivants utilisent l'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>
+Les implémentations de cette interface sont des
+objets liés (des listeners dans ce cas) à la classe nommée <code>ClassUnderTest</code>:
+</p>
+<pre>
+public class ClassUnderTest {
+
+    private Collaborator listener;
+    // ...
+    public void setListener(Collaborator listener) {
+        this.listener = listener;
+    }
+    public void addDocument(String title, byte[] document) { 
+        // ... 
+    }
+    public boolean removeDocument(String title) {
+        // ... 
+    }
+    public boolean removeDocuments(String[] titles) {
+        // ... 
+    }
+}
+</pre>
+<p>
+Le code de la classe et de l'interface est disponible dans
+le package <code>org.easymock.samples</code> dans <code>easymock-3.2-samples.jar</code>
+inclue dans la livraison d'EasyMock.
+</p>
+<p>
+Les exemples qui suivent supposent que vous êtes familier avec le framework de test JUnit.
+Bien que les tests montrés ici utilisent JUnit 4, vous pouvez également utiliser JUnit 3 ou TestNG.
+</p>
+<h3>
+Votre premier Mock Object
+</h3>
+<p>
+Nous allons maintenant construire un cas de test et jouer avec pour
+comprendre les fonctionnalités du package EasyMock. Le
+fichier <code>easymock-3.2-samples.jar</code> contient une version modifiée de ce test. 
+Notre premier test devra vérifier que la suppression d'un document non existant <strong>ne doit pas</strong>
+provoquer la notification de l'objet lié. Voici le test dans la définition du 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.setListener(mock);
+    }
+
+    @Test
+    public void testRemoveNonExistingDocument() {    
+        // This call should not lead to any notification
+        // of the Mock Object: 
+        classUnderTest.removeDocument("Does not exist");
+    }
+}
+</pre>
+<p>
+Pour beaucoup de tests utilisant EasyMock, nous avons
+uniquement besoin de l'import statique des méthodes de la classe
+<code>org.easymock.EasyMock</code>.
+Cette classe est la seule non interne et non dépréciée d'EasyMock 2.
+</p>
+<pre>
+import static org.easymock.EasyMock.*;
+import org.junit.*;
+
+public class ExampleTest {
+
+    private ClassUnderTest classUnderTest;
+    private Collaborator mock;
+    
+}    
+</pre>
+<p>
+Pour obtenir un Mock Object, il faut:
+</p>
+<ol>
+<li>créer un Mock Object pour l'interface à simuler,
+</li>
+<li>enregistrer le comportement attendu, puis
+</li>
+<li>basculer le Mock Object à l'état 'replay'.
+</li>
+</ol>
+<p>
+Voici le premier exemple:
+</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>
+Après activation à l'étape 3, <code>mock</code> 
+est un Mock Object de l'interface <code>Collaborator</code>
+qui n'attend aucun appel. Cela signifie que si nous changeons notre <code>ClassUnderTest</code> 
+pour appeler n'importe quelle méthode de l'interface, le Mock Object lèvera 
+une <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>
+    Utiliser les annotations
+</h3>
+<p>
+Depuis EasyMock 3.2, il est maintenant possible de créer un Mock Object à l'aide d'annotations. C'est une méthode
+à la fois simple et rapide pour créer vos Mock Objects et les injecter à la classe testée. Reprenons l'exemple
+ci-dessus en utilisant les annotations:
+</p>
+<pre>
+import static org.easymock.EasyMock.*;
+
+import org.easymock.EasyMockRunner;
+import org.easymock.TestSubject;
+import org.easymock.Mock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+ at RunWith(EasyMockRunner.class)
+public class ExampleTest {
+
+    @TestSubject
+    private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2
+
+    @Mock
+    private Collaborator mock; // 1
+
+    @Test
+    public void testRemoveNonExistingDocument() {
+        replay(mock);
+        classUnderTest.removeDocument("Does not exist");
+    }
+}
+</pre>
+<p>
+Le <code>mock</code> est instancié par le runner à l'étape 1. Il est ensuite assigné, toujours par le runner,
+au champs <code>listener</code> de <code>classUnderTest</code> à l'étape 2. La méthode <code>setUp</code> n'est
+donc plus nécessaire étant donné que toute l'initialisation a déjà été effectuée par le runner.
+</p>
+<h3>
+   Ajouter un comportement
+</h3>
+<p>
+Écrivons un second test. Si un document est ajouté à
+la classe testée, nous nous attendons à un appel à
+<code>mock.documentAdded()</code>
+sur le Mock Object avec le titre du document en argument:
+</p>
+<pre>
+    @Test
+    public void testAddDocument() {
+        mock.documentAdded("New Document"); // 2
+        replay(mock); // 3
+        classUnderTest.addDocument("New Document", new byte[0]); 
+    }
+</pre>
+<p>
+Aussi, dans l'étape d'enregistrement (avant d'appeler <code>replay</code>),
+le Mock Object ne se comporte pas comme<em></em> un Mock Object mais enregistre 
+les appels de méthode. Après l'appel à <code>replay</code>,
+il se comporte comme un Mock Object, vérifiant que les appels 
+de méthode attendus ont bien lieu.
+</p>
+<p>
+Si <code>classUnderTest.addDocument("New Document", new byte[0])</code>
+appelle la méthode attendue avec un mauvais argument, le
+Mock Object lèvera une <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>
+Tous les appels attendus n'ayant pas eu lieu sont montrés, ainsi
+que tous les appels faits alors qu'ils étaient non attendus
+(aucun dans notre cas). Si l'appel à la méthode est
+effectué trop de fois, le Mock Object le signale
+également:
+</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>
+Vérifier le comportement
+</h3>
+<p>
+Il y a un type d'erreur dont nous ne nous sommes pas
+préoccupés jusqu'à présent: si nous décrivons un
+comportement, nous voulons vérifier qu'il est bien respecté. 
+Le test qui suit passe si une méthode du Mock Object est appelée. 
+Pour vérifier cela, nous devons appeler <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>
+Si la méthode du Mock Object n'est pas appelée, 
+l'exception suivante sera levée :
+</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>
+Le message de l'exception liste tous les appels attendus qui n'ont pas eu lieu.
+</p>
+<h3>
+Attendre un nombre explicite d'appels
+</h3>
+<p>
+Jusqu'à maintenant, nos tests ont été faits uniquement
+sur un seul appel de méthode. Le test suivant
+vérifiera que l'ajout d'un document déjà existant
+déclenche l'appel à <code>mock.documentChanged()</code>
+avec l'argument approprié. Pour en être certain, nous
+vérifions cela trois fois (après tout, c'est un exemple
+;-)):
+</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>
+Afin d'éviter la répétition de <code>mock.documentChanged("Document")</code>,
+EasyMock fournit un raccourci. Nous pouvons spécifier le nombre d'appel avec la méthode
+<code>times(int times)</code> sur l'objet retourné par <code>expectLastCall()</code>.
+Le code ressemble alors à cela:
+</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>
+Si la méthode est appelée un trop grand nombre de fois,
+une exception sera levée nous indiquant que la méthode a
+été appelée trop de fois.
+L'erreur est levée immédiatement après le premier
+appel dépassant la limite:
+</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>
+S'il y a trop peu d'appels, <code>verify(mock)</code>
+lève une <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>
+Spécifier des valeurs de retour
+</h3>
+<p>
+Pour spécifier des valeurs de retour, nous encapsulons l'appel attendu dans
+<code>expect(T value)</code> et spécifions la valeur de retour avec la 
+méthode <code>andReturn(Object returnValue)</code> sur l'objet retourné par
+<code>expect(T value)</code>.
+</p>
+<p>
+Prenons par exemple la vérification du workflow lors de la suppression d'un document. 
+Si <code>ClassUnderTest</code> fait un appel pour supprimer un document, 
+il doit demander aux objets liés de voter pour cette suppression 
+par appel à <code>byte voteForRemoval(String title)</code>.
+Une réponse positive approuve la suppression. Si la somme de
+toutes les réponses est positive, alors le document est
+supprimé et l'appel à <code>documentRemoved(String title)</code> 
+est effectué sur les objets liés:
+</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>
+Le type de la valeur de retour est vérifié à la
+compilation. Par exemple, le code suivant ne compilera pas du fait que
+le type fourni ne correspond au type retourné par la
+méthode:
+</p>
+<pre>
+    expect(mock.voteForRemoval("Document")).andReturn("wrong type");
+</pre>
+<p>
+Au lieu d'appeler <code>expect(T value)</code> pour
+récupérer l'objet auquel affecter une valeur de retour, 
+nous pouvons aussi utiliser l'objet retourné par <code>expectLastCall()</code>.
+Ainsi, au lieu de 
+</p>
+<pre>
+    expect(mock.voteForRemoval("Document")).andReturn((byte) 42);
+</pre>
+<p>
+nous pouvons écrire
+</p>
+<pre>
+    mock.voteForRemoval("Document");
+    expectLastCall().andReturn((byte) 42);
+</pre>
+<p>
+Ce type d'écriture doit uniquement être utilisé
+si la ligne est trop longue car il n'inclut pas la vérification
+du type à la compilation.
+</p>
+<h3>
+Travailler avec les exceptions
+</h3>
+<p>
+Afin de spécifier les exceptions (plus précisément:
+les Throwables) devant être levées, l'objet
+retourné par <code>expectLastCall()</code> et <code>expect(T value)</code> 
+fournit la méthode <code>andThrow(Throwable throwable)</code>.
+Cette méthode doit être appelée durant l'étape
+d'enregistrement après l'appel au Mock Object pour lequel le <code>Throwable</code>
+doit être levé.
+</p>
+<p>
+Les exception non "checkées" (comme <code>RuntimeException</code>,
+<code>Error</code> ainsi que toutes leurs sous classes) peuvent
+être levées de n'importe quelle méthode. Les
+exceptions "checkées" ne doivent être levées que 
+pour méthodes où cela est prévu.
+</p>
+<h3>
+Créer des valeurs de retour ou des exceptions
+</h3>
+<p>
+Parfois, nous voulons que notre Mock Object retourne une valeur ou
+lève une exception créée au moment de l'appel.
+Depuis la version 2.2 d'EasyMock, l'objet retourné 
+par <code>expectLastCall()</code> et <code>expect(T value)</code> fournit la méthode
+<code>andAnswer(IAnswer answer)</code> permettant de spécifier une implémentation 
+de l'interface <code>IAnswer</code> utilisée pour créer 
+une valeur de retour ou une exception.
+</p>
+<p>
+Au sein d'<code>IAnswer</code>, les arguments passés lors de l'appel au mock sont 
+disponibles via <code>EasyMock.getCurrentArguments()</code>.
+Si vous utilisez cela, les refactorings du type réorganisation
+de l'ordre des arguments briseront vos tests. Vous êtes prévenu.
+</p>
+<p>
+Une alternative à <code>IAnswer</code> sont les méthodes <code>andDelegateTo</code> et 
+<code>andStubDelegateTo</code>. Elles permettent de déléguer un appel à une
+implémentation concrète de l'interface "mockées" et qui fournira la valeur de retour. 
+L'avantage est que les paramètres normalement récupéré avec <code>EasyMock.getCurrentArguments()</code> 
+pour <code>IAnswer</code> sont maintenant passés à la méthode de l'implémentation concrète. 
+Ça supporte donc le refactoring. Le désavantage est qu'il faut fournir une implémentation... 
+ce qui resemble un peu à faire un mock à la main. Ce que vous tentez d'éviter en utilisant 
+EasyMock. Il peut aussi être pénible d'implémenter l'interface si celle-ci à beaucoup de méthodes. Finalement, 
+le type de l'implémentation ne peut être vérifié statiquement par rapport au type du Mock Object. 
+Si pour une quelconque raison, la class concrète n'implémente plus la méthode sur laquelle est 
+délégué l'appel, vous aurez une exception lors de la phase de "replay". Ce cas devrait toutefois
+être assez rare.  
+</p>
+<p>
+Pour bien comprendre les deux options, voici un exemple:
+</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>
+Changer de comportement sur le même appel de méthode
+</h3>
+<p>
+Il est également possible de spécifier un changement de comportement pour une méthode.
+Les méthodes <code>times</code>, <code>andReturn</code> et <code>andThrow</code>
+peuvent être chaînées. Comme exemple, 
+nous définissons <code>voteForRemoval("Document")</code> pour
+</p>
+<ul>
+<li>retourner 42 pour les trois premiers appels,
+</li>
+<li>lever une <code>RuntimeException</code> sur le quatrième appel,
+</li>
+<li>renvoyer -42 une fois.
+</li>
+</ul>
+<pre>
+    expect(mock.voteForRemoval("Document"))
+        .andReturn((byte) 42).times(3)
+        .andThrow(new RuntimeException(), 4)
+        .andReturn((byte) -42);
+</pre>
+<h3>
+Être plus permissif sur le nombre d'appels
+</h3>
+<p>
+Afin d'être plus permissif sur le nombre d'appels attendus,
+des méthodes additionnelles peuvent être
+utilisées à la place de <code>times(int count)</code>:
+</p>
+<dl>
+<dt><code>times(int min, int max)</code></dt> 
+<dd>pour attendre entre <code>min</code> and <code>max</code> appels,</dd>
+<dt><code>atLeastOnce()</code></dt>
+<dd>pour attendre au moins un appel, et</dd>
+<dt><code>anyTimes()</code></dt>
+<dd>pour attendre une quantité non définie d'appels.</dd>
+</dl>
+<p>
+Si aucun nombre d'appels n'est explicitement défini,
+alors seul un appel est attendu. Pour le définir explicitement,
+vous pouvez utiliser <code>once()</code> ou <code>times(1)</code>.
+</p>
+<h3>
+Mocks stricts
+</h3>
+<p>
+Sur un Mock Object retourné par <code>EasyMock.createMock()</code>,
+l'ordre d'appel des méthodes n'est pas vérifié.
+Si vous souhaitez avoir un Mock Object 'strict' vérifiant cet ordre,
+utilisez <code>EasyMock.create<i>Strict</i>Mock()</code>.</p>
+<p>
+Lorsqu'un appel inattendu à une méthode est fait sur
+un Mock Object 'strict', le message de l'exception contient les appels 
+de méthode attendus à ce moment, suivi du premier appel en
+conflit. <code>verify(mock)</code> montre tous les appels de méthode manqués.
+</p>
+<h3>
+Activer/Désactiver la vérification de l'ordre d'appel des méthodes
+</h3>
+<p>
+Il est parfois nécessaire qu'un Mock Object vérifie
+l'ordre d'appel sur certains appels uniquement. Pendant la phase
+d'enregistrement, vous pouvez activer la vérification de l'ordre
+d'appel en utilisant <code>checkOrder(mock, true)</code> et la 
+désactiver en utilisant <code>checkOrder(mock, false)</code>.
+</p>
+<p>
+Il y a deux différences entre un Mock Object 'strict' et un Mock Object 'normal':
+</p>
+<ol>
+	<li> Un mock 'strict' a la vérification de l'ordre d'appel activé à la création. </li>
+	<li> Un mock 'strict' a la vérification de l'ordre d'appel activé après un reset (voir <em>Réutilisation d'un Mock Object</em>). </li>
+</ol>
+<h3>
+Définir des comparateurs d'arguments pour plus de souplesse
+</h3>
+<p>
+Pour vérifier la correspondance à un appel de méthode prévu sur un Mock Object, 
+les arguments<code> de type Object</code> sont comparés, par défaut, avec
+<code>equals()</code>. Cela peut introduire des problèmes. Considérons l'exemple suivant:
+</p>
+<pre>
+String[] documents = new String[] { "Document 1", "Document 2" };
+expect(mock.voteForRemovals(documents)).andReturn(42);
+</pre>
+<p>
+Si la méthode est appelée avec un autre tableau ayant le même contenu,
+cela provoque une exception du fait que <code>equals()</code> compare l'identité 
+des objets pour les tableaux:
+</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>
+Pour spécifier que seule l'égalité de tableau
+est nécessaire pour cet appel, utilisez la méthode 
+<code>aryEq</code>, importée statiquement de la classe <code>EasyMock</code>:
+</p>
+<pre>
+String[] documents = new String[] { "Document 1", "Document 2" };
+expect(mock.voteForRemovals(aryEq(documents))).andReturn(42);
+</pre>
+<p>
+Si vous souhaitez utiliser les comparateurs lors d'un appel, vous devez
+en utiliser pour chaque argument de la méthode appelée.
+</p>
+<p>
+Voici quelques comparateurs prédéfinis disponible:
+</p>
+<dl>
+
+<dt><code>eq(X value)</code></dt>
+<dd>Vérifie que la valeur reçue égale la valeur attendue. Disponible pour tous les types primitifs et objets.</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>, <code>anyString()</code></dt>
+<dd>Laisse passer n'importe quelle valeur. Disponible pour tous les types primitifs et objets.</dd>
+
+<dt><code>eq(X value, X delta)</code></dt>
+<dd>Vérifie que la valeur reçue égale la valeur attendue, plus ou moins un delta. Disponible pour les <code>float</code> et <code>double</code>.</dd>
+
+<dt><code>aryEq(X value)</code></dt>
+<dd>Vérifie que la valeur reçue égale la valeur attendue en s'appuyant sur <code>Arrays.equals()</code>. Disponible pour les tableaux d'objets et de types primitifs.</dd>
+
+<dt><code>isNull()</code>, <code>isNull(Class clazz)</code></dt>
+<dd>Vérifie que la valeur reçue est nulle. Disponible pour les objets.</dd>
+
+<dt><code>notNull()</code>, <code>notNull(Class clazz)</code></dt>
+<dd>Vérifie que la valeur reçue n'est pas nulle. Disponible pour les objets.</dd>
+
+<dt><code>same(X value)</code></dt>
+<dd>Vérifie que la valeur reçue est la même que la value attendue. Disponible pour les objets.</dd>
+
+<dt><code>isA(Class clazz)</code></dt>
+<dd>Vérifie que la valeur reçue est une instance de clazz ou d'une classe hérite ou implémente clazz. Disponible pour les objets.</dd>
+
+<dt><code>lt(X value)</code>, <code>leq(X value)</code>, <code>geq(X value)</code>, <code>gt(X value)</code></dt>
+<dd>Vérifie que la valeur reçue est inférieure/inférieure ou égale/supérieure
+ou égale/supérieure à la valeur attendue. Disponible pour tous les types primitifs numériques et les implémentations de <code>Comparable</code>.</dd>
+
+<dt><code>startsWith(String prefix), contains(String substring), endsWith(String suffix)</code></dt>
+<dd>Vérifie que la valeur reçue commence par/contient/se termine par la valeur attendue. Disponible pour les <code>String</code>s.</dd>
+
+<dt><code>matches(String regex), find(String regex)</code></dt>
+<dd>Vérifie que la valeur reçue/une sous-chaîne de la valeur reçue correspond à l'expression ré. Disponible pour les <code>String</code>s.</dd>
+
+<dt><code>and(X first, X second)</code></dt>
+<dd>Est valide si les résultats des deux comparateurs utilisés en <code>first</code> et <code>second</code> sont vérifiés. Disponible pour tous les types primitifs et objets.</dd>
+
+<dt><code>or(X first, X second)</code></dt>
+<dd>Est valide si l'un des résultats des deux comparateurs utilisés en <code>first</code> et <code>second</code> est vérifié. Disponible pour tous les types primitifs et objets.</dd>
+
+<dt><code>not(X value)</code></dt>
+<dd>Est valide si le résultat du comparateur utilisé dans <code>value</code> est négatif.</dd>
+
+<dt><code>cmpEq(X value)</code></dt>
+<dd>Vérifie que la valeur reçue égale la valeur attendue du point de vue de <code>Comparable.compareTo(X o)</code>. Disponible pour tous les types primitifs numériques et les implémentations de <code>Comparable</code>.</dd>
+
+<dt><code>cmp(X value, Comparator<X> comparator, LogicalOperator operator)</code></dt>
+<dd>Vérifie que <code>comparator.compare(reçue, value) operator 0</code> où <code>operator</code> est <,<=,>,>= ou ==.</dd>
+
+<dt><code>capture(Capture<T> capture)</code>, <code>captureXXX(Capture<T> capture)</code></dt>
+<dd>Laisse passer n'importe quelle valeur mais la capture dans le paramètre <code>Capture</code> pour un usage ultérieurs. Vous pouvez utiliser <code>and(someMatcher(...), capture(c))</code> pour 
+capturer le paramètre d'un appel de méthode en particulier. Vous pouvez aussi spécifier le <code>CaptureType</code> pour indiquer à l'objet
+<code>Capture</code> de conserver le premier (<code>FIRST</code>), le dernier (<code>LAST</code>), tous (<code>ALL</code>) ou aucun (<code>NONE</code>) des objets capturés</dd>
+
+</dl>
+
+<h3>
+Définir son propre comparateur d'arguments
+</h3>
+<p>
+Il peut être intéressant de définir son propre
+comparateur d'argument. Prenons un comparateur dont le rôle
+serait de vérifier une exception par rapport à son
+type et message. Il pourrait être utilisé de la façon suivante:
+</p>
+<pre>
+    IllegalStateException e = new IllegalStateException("Operation not allowed.")
+    expect(mock.logThrowable(eqException(e))).andReturn(true);
+</pre>
+<p>
+Deux étapes sont nécessaires pour réaliser cela: le nouveau comparateur
+doit être défini et la méthode statique <code>eqException</code> 
+doit être déclarée.
+</p>
+<p>
+Pour définir le nouveau comparateur d'argument, nous implémentons l'interface <code>org.easymock.IArgumentMatcher</code>.
+Cette interface contient deux méthodes: <code>matches(Object actual)</code>, vérifiant 
+que l'argument reçu est bien celui attendu, et <code>appendTo(StringBuffer buffer)</code>,
+ajoutant au StringBuffer une chaîne de caractères représentative du comparateur d'argument.
+L'implémentation est la suivante :
+</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>
+La méthode <code>eqException</code> doit instancier le
+comparateur d'argument avec l'objet Throwable donné, le fournir
+à EasyMock via la méthode statique <code>reportMatcher(IArgumentMatcher matcher)</code>
+et retourner une valeur afin d'être utilisée au sein de l'appel à la méthode mockée 
+(typiquement <code>0</code>, <code>null</code> ou <code>false</code>). Une première tentative ressemblerait à ceci:
+</p>
+<pre>
+public static Throwable eqException(Throwable in) {
+    EasyMock.reportMatcher(new ThrowableEquals(in));
+    return null;
+}
+</pre>
+<p>
+Cependant, cela ne fonctionnerait que si la méthode <code>logThrowable</code>
+de l'exemple acceptait <code>Throwable</code>s et quelque chose de plus spécifique du style de <code>RuntimeException</code>. 
+Dans ce dernier cas, le code de notre exemple ne compilerait pas:
+</p>
+<pre>
+    IllegalStateException e = new IllegalStateException("Operation not allowed.")
+    expect(mock.logThrowable(eqException(e))).andReturn(true);
+</pre>
+<p>
+Java 5.0 à la rescousse: Au lieu de définir <code>eqException</code>
+avec un <code>Throwable</code> en paramètre, nous utilisons un type générique 
+qui hérite de <code>Throwable</code>:
+</p>
+<pre>
+public static <T extends Throwable> T eqException(T in) {
+    reportMatcher(new ThrowableEquals(in));
+    return null;
+}
+</pre>
+<h3>
+Réutilisation d'un Mock Object
+</h3>
+<p>
+Les Mock Objects peuvent être réinitialisés avec <code>reset(mock)</code>.
+</p>
+<p>
+Au besoin, un Mock Object peut aussi être converti d'un type à l'autre en appelant <code>resetToNice(mock)</code>, 
+<code>resetToDefault(mock)</code> ou <code>resetToStrict(mock)</code>.
+</p>
+<h3>
+Utilisation d'un comportement de "stub" pour les méthodes
+</h3>
+<p>
+Dans certains cas, nous voudrions que nos Mock Object répondent
+à certains appels, mais sans tenir compte du nombre de fois, de l'ordre
+ni même s'ils ont été eu lieu.
+Ce comportement de "stub" peut être défini en utilisant
+les méthodes <code>andStubReturn(Object value)</code>, 
+<code>andStubThrow(Throwable throwable)</code>, <code>andStubAnswer(IAnswer<t> answer)</code>
+et <code>asStub()</code>. Le code suivant configure le Mock Object pour répondre 42 
+à <code>voteForRemoval("Document")</code> une fois et -1 pour tous les autres arguments:
+</p>
+<pre>
+    expect(mock.voteForRemoval("Document")).andReturn(42);
+    expect(mock.voteForRemoval(not(eq("Document")))).andStubReturn(-1);
+</pre>
+<h3>
+Création de mocks dits "gentils"
+</h3>
+<p>
+Pour un Mock Object retourné par <code>createMock()</code>, le comportement par défaut pour toutes 
+les méthodes est de lever une <code>AssertionError</code> pour tous les appels non prévus.
+Si vous souhaitez avoir un Mock Object "gentil" autorisant, par défaut, l'appel à 
+toutes les méthodes et retournant la valeur vide appropriée (<code>0</code>, <code>null</code>
+ou <code>false</code>), utilisez <code>create<i>Nice</i>Mock()</code> au lieu de <code>createMock()</code>.
+</p>
+
+<a id="Object_Methods"/><h3>Méthodes de la classe Object</h3>
+<p>
+Les comportements des quatre méthodes <code>equals()</code>,
+<code>hashCode()</code>, <code>toString()</code> et <code>finalize()</code>
+ne peuvent être changés sur des Mock Objects créés avec EasyMock,
+même si elles font partie de l'interface duquel le Mock Object est créé.
+</p>
+<h3>Vérifier l'ordre d'appel des méthodes entre plusieurs Mocks</h3>
+<p>
+Jusqu'à présent, nous avons vu un Mock Object comme étant
+seul et configuré par les méthodes statiques de la classe <code>EasyMock</code>. 
+Mais beaucoup de ces méthodes statiques font référence à l'objet "control"
+caché de chaque Mock Object et lui délègue l'appel. Un
+Mock Control est un objet implémentant l'interface <code>IMocksControl</code>.
+</p>
+<p>
+Du coup, au lieu de
+</p>
+<pre>
+    IMyInterface mock = createStrictMock(IMyInterface.class);
+    replay(mock);
+    verify(mock); 
+    reset(mock);
+</pre>
+<p>
+nous pourrions utiliser le code équivalent:
+</p>
+<pre>
+    IMocksControl ctrl = createStrictControl();
+    IMyInterface mock = ctrl.createMock(IMyInterface.class);
+    ctrl.replay();
+    ctrl.verify(); 
+    ctrl.reset();
+</pre>
+<p>
+L'interface <code>IMocksControl</code> permet de créer plus d'un seul Mock Object. 
+Ainsi, il est possible de vérifier l'ordre d'appel des méthodes entre les mocks. 
+Par exemple, configurons deux mock objects pour l'interface <code>IMyInterface</code> pour lesquels 
+nous attendons respectivement les appels à <code>mock1.a()</code> et <code>mock2.a()</code>, 
+un nombre indéfini d'appels à <code>mock1.c()</code> et <code>mock2.c()</code>, 
+et enfin <code>mock2.b()</code> et <code>mock1.b()</code>, dans cet ordre:
+</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>Nommer un Mock Object</h3>
+<p>
+Les Mock Objects peuvent ê nommés à leur création en utilisant 
+<code>createMock(String name, Class<T> toMock)</code>,
+<code>createStrictMock(String name, Class<T> toMock)</code> ou
+<code>createNiceMock(String name, Class<T> toMock)</code>.
+Les noms seront affichés dans le message des <code>AssertionError</code>.
+</p>
+<h3>Sérializer un Mock Object</h3>
+<p>
+Un Mock Object peut être sérializé à n'importe quelle étape de son 
+existence. Il y a toutefois des contraintes évidentes:
+</p>
+<ul>
+<li>Les comparateurs d'arguments utilisés doivent être sérializable (ceux fournis avec EasyMock le sont)
+</li>
+<li>Les paramètres enregistrés doivent être sérializable
+</li>
+</ul>
+<h3>Traitement multifil</h3>
+<p>
+Pendant la phase d'enregistrement un Mock Object <b>n'est pas</b> à fil sécurisé. Un Mock Object donné (ou des Mock Objects liés au
+même <code>IMocksControl</code>) ne peut être enregistré que d'un seul fil. Toutefois, plusieurs Mock Objects peuvent être enregistrés
+simultanément dans des fils différents.
+</p>
+<p>
+Durant la phase de rejeu, un Mock Object sera à fil sécurisé par défaut. Ceci peut être changé en appelant <code>makeThreadSafe(mock, false)</code>.
+durant la phase d'enregistrement. Cela peut permettre d'éviter des interblocages dans certaines rares situations.
+</p>
+<p>
+Finallement, appeler <code>checkIsUsedInOneThread(mock, true)</code> permet de s'assurer qu'un Mock Object ne sera appelé que d'un seul
+fil. Une exception sera lancé sinon. Cela peut être pratique dans le cas où l'objet "mocké" n'est pas à fil sécurisé et que l'on veut
+s'assurer qu'il est utilisé correctement.
+</p>
+<h3>EasyMockSupport</h3>
+<p>
+<code>EasyMockSupport</code> est une classe ayant pour but d'être utilisée comme classe utilitaire ou comme classe de base de vos classes 
+de test. Elle se souvient de tous les "Mock Objects" créés (ou en fait de tous les "Mock Controls" créés) pour pouvoir faire un replay, 
+reset ou verify de tous en un seul coup. Voici un exemple utilisant JUnit:
+</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() {
+        // phase de création
+        firstCollaborator = createMock(Collaborator.class);
+        secondCollaborator = createMock(Collaborator.class);
+        classUnderTest.addListener(firstCollaborator);
+        classUnderTest.addListener(secondCollaborator);
+
+        // phase d'enregistrement
+        firstCollaborator.documentAdded("New Document");
+        secondCollaborator.documentAdded("New Document");
+        
+        replayAll(); // tous les mocks d'un seul coup
+        
+        // test
+        classUnderTest.addDocument("New Document", new byte[0]);
+                
+        verifyAll(); // tous les mocks d'un seul coup
+    }
+}
+</pre>
+<h3>Modifier les comportements par défaut d'EasyMock</h3>
+<p>
+EasyMock fournit un mécanisme de gestion de propriétés permettant de modifier son comportement. Il vise
+principalement à permettre le retour à un comportement antérieur à la version courante. Les propriétés
+actuellement supportées sont:
+</p>
+<dl>
+<dt><code>easymock.notThreadSafeByDefault</code></dt>
+<dd>Si true, les Mock Objects ne seront pas à fil sécurisé par défaut. Values possibles: "true" ou "false". Défaut: false</dd>
+<dt><code>easymock.enableThreadSafetyCheckByDefault</code></dt>
+<dd>Si true, un mock ne pourra être appelé que d'un seul fil. Values possibles: "true" ou "false". Défaut: false</dd>
+<dt><code>easymock.disableClassMocking</code></dt>
+<dd>Ne pas permettre le mocking de classes (permettre uniquement le mocking d'interfaces). Valeurs possibles: "true" ou "false". Défaut: false</dd>
+</dl>
+<p>
+Les propriétés peuvent être fixées de deux façons.
+</p>
+<ul>
+<li>Dans le fichier <code>easymock.properties</code> mis dans le package défaut du classpath 
+</li>
+<li>En appelant <code>EasyMock.setEasyMockProperty</code>. Des constantes sont disponibles 
+dans la classe <code>EasyMock</code>. Évidemment, fixer une propriété dans le code écrase
+toute propriété mise dans <code>easymock.properties</code>
+</li>
+</ul>
+<h3>
+Compatibilité avec les anciennes versions
+</h3>
+<p>EasyMock 3 fournit toujours le project Class Extension (qui est toutefois déprécié) pour
+permettre une migration plus facile de EasyMock 2 vers EasyMock 3. Il s'agit d'une compatibilité des
+sources et non des binaires. Le code devra donc être recompilé. 
+</p>
+<p>EasyMock 2.1 introduisait une fonctionnalité de callback
+qui a été retirée dans EasyMock 2.2, car trop complexe. 
+Depuis EasyMock 2.2, l'interface <code>IAnswer</code>
+fournit la fonctionnalité de callback. 
+</p>
+<h3>OSGi</h3>
+<p>
+Le jar d'EasyMock peut être utilisé comme bundle OSGi. Il export les packages
+<code>org.easymock</code>, <code>org.easymock.internal</code> 
+et <code>org.easymock.internal.matchers</code>. Toutefois, pour importer les deux
+derniers, vous spécifier l'attribut <code>poweruser</code> à "true" (<code>poweruser=true</code>). 
+Ces packages sont prévus d'être utilisés pour étendre EasyMock, ils n'ont donc pas besoins d'être
+importés habituellement.
+</p>
+<h3>Mocking partiel</h3>
+<p>
+Dans certains cas, vous pouvez avoir besoin de "mocker" uniquement certaines
+méthodes d'une classe et de conserver un comportement normal pour
+les autres. Cela arrive habituellement lorsque pour souhaitez tester une
+méthode appelant d'autres méthodes de la même classe.
+Vous voulez donc garder le comportement normal de la méthode testée
+et "mocker" les autres.
+</p>
+<p>
+Dans ce cas, la premier réflexe à avoir est
+d'envisager un refactoring car, bien souvent, ce problème est la
+conséquence d'un mauvais design. Si ce n'est pas le cas ou si
+vous ne pouvez faire autrement pour une quelconque contrainte de 
+développement, voici la solution:
+</p>
+<pre>
+ToMock mock = createMockBuilder(ToMock.class)
+   .addMockedMethod("mockedMethod").createMock();
+</pre>
+<p>Seules les méthodes ajoutées avec <code>addMockedMethod(s)</code> seront
+"mockées" (<code>mockedMethod()</code> dans l'exemple). Les autres conservent leur
+comportement habituel. Une exception: les méthodes abstraites sont "mockées" par défaut.
+</p>
+<p><code>createMockBuilder</code> retourne l'interface <code>IMockBuilder</code>. Elle contient
+diverses méthodes pour facilement créer un mock partiel. Jettez un coup d'oeil à la javadoc
+pour en savoir plus.
+</p>
+<p><b>Remarque:</b> EasyMock fournit un comportement par défault pour les méthodes de la classe 
+Object (<i>equals, hashCode, toString, finalize</i>). Toutefois, pour un mock partiel, si ces méthodes ne sont pas
+mockées explicitement, elles auront leur comportement normal et non celui par défaut d'EasyMock.
+</p>
+<h3>Test interne d'une classe</h3>  
+<p>
+Il est possible de créer un mock en appelant un constructeur de la classe. Ceci
+peut être utile lorsqu'une méthode doit être testée mais d'autres
+dans la même classe "mockées". Pour cela vous devez faire quelque chose comme
+</p>
+<pre>
+ToMock mock = createMockBuilder(ToMock.class)
+   .withConstructor(1, 2, 3); // 1, 2, 3 sont les paramètres passés au constructeur
+</pre>
+<p>
+Voir <code>ConstructorCalledMockTest</code> pour un exemple d'utilisation.
+</p>
+<h3>Remplacer l'instantiateur de classes par défaut</h3>
+<p>
+Parfois (habituellement à cause d'une JVM non supportée), il est possible
+que EasyMock ne soit pas capable de créer un mock dans votre environnement java.
+Sous le capot, l'instantiation de classes est implémentée par un pattern "factory".
+En cas de problème, vous pouvez remplacer l'instantiateur par défaut avec:
+</p>
+<ul>
+<li>L'ancien <code>DefaultClassInstantiator</code> qui fonctionne très bien avec les classes
+sérializable et sinon tente de deviner quel constructeur appeler et quels paramètres lui passer.</li>
+<li>Votre propre instantiateur. Celui-ci doit implémenter <code>IClassInstantiator</code>.</li>
+</ul>
+<p>
+Vous assignez ce nouvel instantiateur à l'aide de <code>ClassInstantiatorFactory.setInstantiator()</code>.
+Vous pouvez remettre celui par défaut avec <code>setDefaultInstantiator()</code>.
+</p>
+<p>
+<b>Important:</b>
+L'instantiateur est gardé statiquement et reste donc entre deux tests. Assurez-vous
+de le réinitialiser si nécessaire.
+</p>
+<h3>Sérializer une classe mockée</h3>
+<p>
+Une class mockée peut aussi être sérializé. Toutefois, comme celle-ci étant une classe sérializable,
+cette dernière peut avoir un comportement spécial dû à l'implémentation de méthodes tels 
+que <code>writeObject</code>. Ces méthodes seront toujours appelées lorsque le mock sera sérializé
+et peuvent potentiellement échouer. Habituellement, le contournement consiste à créer le mock
+en appelant un constructeur.
+</p>
+<p>
+Aussi, il est possible que la dé-sérialization d'un mock ne fonctionne pas si elle est effectuée dans
+un class loader différent de la sérialization. Ce cas n'a pas été testé.
+</p>
+<h3>Limitations du mocking de classes</h3>
+<p> 
+Pour être cohérent avec le mocking d'interfaces, EasyMock fournit aussi un comportement par défaut 
+pour <code>equals()</code>, <code>toString()</code>, <code>hashCode()</code> et <code>finalize()</code> pour les classes mockées. 
+Cela signifie que vous ne pourrez enregistrer votre propre comportement pour ces méthodes. Cette 
+limitation être considérée comme une fonctionnalité permettant de ne pas s'occuper de ces
+méthodes.
+</p>
+<p>
+Les méthodes finales ne peuvent pas être "mockées". Si
+appelées, leur code normal sera exécuté.
+</p>
+<p>
+Les méthodes privées ne peuvent être "mockées". Si
+appelées, leur code normal sera exécuté. Pour un mock partiel, si
+la méthode testée appelle une méthode privée, vous devrez aussi tester
+cette dernière étant donné que vous ne pouvez pas la mocker.
+</p>
+<p>
+L'instantiation des classes est faite par 
+<a href="http://objenesis.googlecode.com/svn/docs/index.html">Objenesis</a>.
+Les JVMs supportées sont listées <a href="http://code.google.com/p/objenesis/wiki/ListOfCurrentlySupportedVMs">ici</a>.
+</p>
+<h3>Support Android</h3>
+<p>
+    Depuis la version 3.2, EasyMock peut être utilisé sur une VM Android (Dalvik). Il suffit d'ajouter la dépendance à
+    votre projet apk utilisé pour les tests de votre applicaiton. Il est aussi préférable d'exclure cglib étant donné
+    que dexmaker sera de toute façon utiliser en remplacement. Vous devrez aussi ajouter dexmaker explicitement étant
+    donné qu'il s'agit d'une dépendance optionnelle. Si vous utilisez Maven, vous finirez avec les dépendances suivantes
+</p>
+<pre>
+<dependency>
+  <groupId>org.easymock</groupId>
+  <artifactId>easymock</artifactId>
+  <version>3.2</version>
+  <exclusions>
+    <exclusion>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+    </exclusion>
+  </exclusions>
+</dependency>
+<dependency>
+  <groupId>com.google.dexmaker</groupId>
+  <artifactId>dexmaker</artifactId>
+  <version>1.0</version>
+</dependency>
+</pre>
+<h2>
+Développement d'EasyMock
+</h2>
+<p>
+EasyMock a été développé par Tammo Freese chez OFFIS. La maintenance est effectuée
+par Henri Tremblay depuis 2007. Le développement d'EasyMock est hébergé par 
+<a href="http://sourceforge.net/projects/easymock/">SourceForge</a>
+pour permettre à d'autres développeurs et sociétés d'y contribuer.
+</p>
+<p>
+Les Mock Objects de classes (précédemment appelé EasyMock Class Extension) ont été initialement 
+développée par Joel Shellman, Chad Woolley et Henri Tremblay dans la section 
+fichiers du of Yahoo!Groups.
+</p>
+<p>
+Remerciements à ceux qui nous ont fourni retour d'expérience et rustines, incluant
+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 et de nombreux autres.
+</p>
+<p>
+Merci de consulter la <a href="http://www.easymock.org">page d'accueil EasyMock</a> 
+pour être informé des nouvelles versions et transmettez vos bogues et suggestions à
+<a href="mailto:easymock at yahoogroups.com?subject=EasyMock ${project.version} feedback">EasyMock Yahoo!Group</a> (en anglais SVP).
+Si vous souhaitez souscrire au EasyMock Yahoo!Group, envoyez un message à
+<a href="mailto:easymock-subscribe at yahoogroups.com">easymock-subscribe at yahoogroups.com</a>.
+</p>
+</div>
+</body>
+</html>
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/License.html b/License.html
deleted file mode 100644
index 5725458..0000000
--- a/License.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!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 License</title>
-	<link rel="stylesheet" href="easymock.css" />
-</head>
-
-<body><div class="bodywidth">
-
-<h2>
-EasyMock 2 License (MIT License)
-</h2>
-
-<em>Copyright (c) 2001-2008 <a href="http://www.offis.de">OFFIS</a>, <a href="http://tammofreese.de">Tammo Freese</a>.</em>
-
-<p>
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-</p>
-<p>
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-</p>
-<p>
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-</p>
-
-</div>
-</body>
-</html>
-
-
diff --git a/easymock.css b/easymock.css
index 30d37e7..fa24362 100644
--- a/easymock.css
+++ b/easymock.css
@@ -3,18 +3,20 @@ body {
         font-size:11pt;
         color:#000000;
         background-color:#ffffff;
-        text-align:left;
+        text-align:justify;
 }
 
 .bodywidth { 
-        width:750px;
+        width:880px;
+        position:absolute;
+        left:50%;
+        margin:0 0 0 -440px;
 }
 
 h1, h2, h3, .contentbar {
         padding:3px;
 }
 
-
 h1, h2, h3 {
         font-weight:bold;
 }
@@ -42,6 +44,37 @@ img {
         border:0;
 }
 
+a:link { 
+        color:#666699;
+        text-decoration:underline;
+}
+
+a:visited {
+        color:#000000;
+        text-decoration:underline;
+}
+
+a:hover { 
+        color:#000000;
+        background-color:#ffffff;
+        text-decoration:none;
+}
+
+a:active { 
+        color:#000000;
+        font-weight:bold;
+        background-color:#ffffff;
+}
+
+a:link.heading, 
+a:visited.heading, 
+a:hover.heading, 
+a:active.heading {
+        color:#000000;
+        background-color:#ffffff;
+        text-decoration:none;
+}
+
 ul {
         list-style-type:square;
 }
@@ -53,3 +86,21 @@ pre {
         font-size:8pt;
         padding:3px;
 }
+
+.buttonactive {
+        color:#990000;
+        font-weight:bold;
+}
+
+.contentbar {    
+        font-size:10pt;
+        text-align:center;
+}
+
+.right {
+        float:right;
+}
+
+.center {
+        text-align:center;
+}
diff --git a/samples/org/easymock/samples/AnnotatedMockTest.java b/samples/org/easymock/samples/AnnotatedMockTest.java
new file mode 100644
index 0000000..4edcb22
--- /dev/null
+++ b/samples/org/easymock/samples/AnnotatedMockTest.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import org.easymock.EasyMockRunner;
+import org.easymock.EasyMockSupport;
+import org.easymock.TestSubject;
+import org.easymock.Mock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Example of how to use <code>@Mock</code> and <code>@TestSubject</code> annotations
+ * 
+ * @author Henri Tremblay
+ */
+ at RunWith(EasyMockRunner.class)
+public class AnnotatedMockTest extends EasyMockSupport {
+
+    @TestSubject
+    private final ClassTested classUnderTest = new ClassTested();
+
+    @Mock
+    private Collaborator collaborator;
+
+    @Test
+    public void addDocument() {
+        collaborator.documentAdded("New Document");
+        replayAll();
+        classUnderTest.addDocument("New Document", new byte[0]);
+        verifyAll();
+    }
+}
diff --git a/samples/org/easymock/samples/BasicClassMockTest.java b/samples/org/easymock/samples/BasicClassMockTest.java
new file mode 100644
index 0000000..705a413
--- /dev/null
+++ b/samples/org/easymock/samples/BasicClassMockTest.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import org.easymock.EasyMockSupport;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Example of how to use <code>org.easymock.classextension.EasyMock</code>
+ * 
+ * @author Henri Tremblay
+ */
+public class BasicClassMockTest extends EasyMockSupport {
+
+    /**
+     * Our nice class that is allowed to print
+     */
+    public static class Document {
+
+        private final Printer printer;
+
+        private String content;
+
+        public Document(final Printer printer) {
+            this.printer = printer;
+        }
+
+        public String getContent() {
+            return content;
+        }
+
+        public void setContent(final String content) {
+            this.content = content;
+        }
+
+        public void print() {
+            printer.print(content);
+        }
+    }
+
+    /**
+     * The terrible 3rd party class that is not an interface but that we really
+     * want to mock.
+     */
+    public static abstract class Printer {
+        public abstract void print(String toPrint);
+    }
+
+    private Printer printer;
+
+    private Document document;
+
+    @Before
+    public void setUp() {
+        printer = createMock(Printer.class);
+        document = new Document(printer);
+    }
+
+    @After
+    public void tearDown() {
+        printer = null;
+        document = null;
+    }
+
+    @Test
+    public void testPrintContent() {
+        printer.print("Hello world");
+        replayAll();
+
+        document.setContent("Hello world");
+        document.print();
+
+        verifyAll(); // make sure Printer.print was called
+    }
+
+    @Test
+    public void testPrintEmptyContent() {
+        printer.print("");
+        replayAll();
+
+        document.setContent("");
+        document.print();
+
+        verifyAll(); // make sure Printer.print was called
+    }
+}
diff --git a/samples/org/easymock/samples/ClassTested.java b/samples/org/easymock/samples/ClassTested.java
new file mode 100644
index 0000000..8c40c81
--- /dev/null
+++ b/samples/org/easymock/samples/ClassTested.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ClassTested {
+
+    private Collaborator listener;
+
+    private final Map<String, byte[]> documents = new HashMap<String, byte[]>();
+
+    public void setListener(final Collaborator listener) {
+        this.listener = listener;
+    }
+
+    public void addDocument(final String title, final byte[] document) {
+        final boolean documentChange = documents.containsKey(title);
+        documents.put(title, document);
+        if (documentChange) {
+            notifyListenersDocumentChanged(title);
+        } else {
+            notifyListenersDocumentAdded(title);
+        }
+    }
+
+    public boolean removeDocument(final String title) {
+        if (!documents.containsKey(title)) {
+            return true;
+        }
+
+        if (!listenersAllowRemoval(title)) {
+            return false;
+        }
+
+        documents.remove(title);
+        notifyListenersDocumentRemoved(title);
+
+        return true;
+    }
+
+    public boolean removeDocuments(final String... titles) {
+        if (!listenersAllowRemovals(titles)) {
+            return false;
+        }
+
+        for (final String title : titles) {
+            documents.remove(title);
+            notifyListenersDocumentRemoved(title);
+        }
+        return true;
+    }
+
+    private void notifyListenersDocumentAdded(final String title) {
+        listener.documentAdded(title);
+    }
+
+    private void notifyListenersDocumentChanged(final String title) {
+        listener.documentChanged(title);
+    }
+
+    private void notifyListenersDocumentRemoved(final String title) {
+        listener.documentRemoved(title);
+    }
+
+    private boolean listenersAllowRemoval(final String title) {
+        return listener.voteForRemoval(title) > 0;
+    }
+
+    private boolean listenersAllowRemovals(final String... titles) {
+        return listener.voteForRemovals(titles) > 0;
+    }
+
+}
diff --git a/samples/org/easymock/samples/ClassUnderTest.java b/samples/org/easymock/samples/ClassUnderTest.java
deleted file mode 100644
index 4fd46e3..0000000
--- a/samples/org/easymock/samples/ClassUnderTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.samples;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class ClassUnderTest {
-
-    private Set<Collaborator> listeners = new HashSet<Collaborator>();
-
-    private Map<String, byte[]> documents = new HashMap<String, byte[]>();
-
-    public void addListener(Collaborator listener) {
-        listeners.add(listener);
-    }
-
-    public void addDocument(String title, byte[] document) {
-        boolean documentChange = documents.containsKey(title);
-        documents.put(title, document);
-        if (documentChange) {
-            notifyListenersDocumentChanged(title);
-        } else {
-            notifyListenersDocumentAdded(title);
-        }
-    }
-
-    public boolean removeDocument(String title) {
-        if (!documents.containsKey(title)) {
-            return true;
-        }
-
-        if (!listenersAllowRemoval(title)) {
-            return false;
-        }
-
-        documents.remove(title);
-        notifyListenersDocumentRemoved(title);
-
-        return true;
-    }
-
-    public boolean removeDocuments(String[] titles) {
-        if (!listenersAllowRemovals(titles)) {
-            return false;
-        }
-
-        for (String title : titles) {
-            documents.remove(title);
-            notifyListenersDocumentRemoved(title);
-        }
-        return true;
-    }
-
-    private void notifyListenersDocumentAdded(String title) {
-        for (Collaborator listener : listeners) {
-            listener.documentAdded(title);
-        }
-    }
-
-    private void notifyListenersDocumentChanged(String title) {
-        for (Collaborator listener : listeners) {
-            listener.documentChanged(title);
-        }
-    }
-
-    private void notifyListenersDocumentRemoved(String title) {
-        for (Collaborator listener : listeners) {
-            listener.documentRemoved(title);
-        }
-    }
-
-    private boolean listenersAllowRemoval(String title) {
-        int result = 0;
-        for (Collaborator listener : listeners) {
-            result += listener.voteForRemoval(title);
-        }
-        return result > 0;
-    }
-
-    private boolean listenersAllowRemovals(String[] titles) {
-        int result = 0;
-        for (Collaborator listener : listeners) {
-            result += listener.voteForRemovals(titles);
-        }
-        return result > 0;
-    }
-
-}
diff --git a/samples/org/easymock/samples/Collaborator.java b/samples/org/easymock/samples/Collaborator.java
index 9526393..6085d4d 100644
--- a/samples/org/easymock/samples/Collaborator.java
+++ b/samples/org/easymock/samples/Collaborator.java
@@ -1,17 +1,31 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-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);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public interface Collaborator {
+    void documentAdded(String title);
+
+    void documentChanged(String title);
+
+    void documentRemoved(String title);
+
+    byte voteForRemoval(String title);
+
+    byte voteForRemovals(String... titles);
+}
diff --git a/samples/org/easymock/samples/ConstructorCalledMockTest.java b/samples/org/easymock/samples/ConstructorCalledMockTest.java
new file mode 100644
index 0000000..15a769f
--- /dev/null
+++ b/samples/org/easymock/samples/ConstructorCalledMockTest.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.math.BigDecimal;
+
+import org.easymock.EasyMockSupport;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Example of how to partial mock with actually calling a constructor
+ * 
+ * @author Henri Tremblay
+ */
+public class ConstructorCalledMockTest extends EasyMockSupport {
+
+    /**
+     * Class to test and partially mock
+     */
+    public static abstract class TaxCalculator {
+
+        private final BigDecimal[] values;
+
+        public TaxCalculator(final BigDecimal... values) {
+            this.values = values;
+        }
+
+        protected abstract BigDecimal rate();
+
+        public BigDecimal tax() {
+            BigDecimal result = BigDecimal.ZERO;
+
+            for (final BigDecimal d : values) {
+                result = result.add(d);
+            }
+
+            return result.multiply(rate());
+        }
+    }
+
+    private TaxCalculator tc;
+
+    @Before
+    public void setUp() {
+        tc = createMockBuilder(TaxCalculator.class).withConstructor(BigDecimal[].class).withArgs(
+                (Object) new BigDecimal[] { new BigDecimal("5"), new BigDecimal("15") }) // varargs are special since they are in fact arrays
+                .createMock(); // no need to mock any methods, abstract ones are mocked by default
+    }
+
+    @After
+    public void tearDown() {
+        verifyAll();
+    }
+
+    @Test
+    public void testTax() {
+
+        expect(tc.rate()).andStubReturn(new BigDecimal("0.20"));
+        replayAll();
+
+        assertEquals(new BigDecimal("4.00"), tc.tax());
+    }
+
+    @Test
+    public void testTax_ZeroRate() {
+
+        expect(tc.rate()).andStubReturn(BigDecimal.ZERO);
+        replayAll();
+
+        assertEquals(BigDecimal.ZERO, tc.tax());
+    }
+}
diff --git a/samples/org/easymock/samples/ExampleTest.java b/samples/org/easymock/samples/ExampleTest.java
index 9ff3c38..169e565 100644
--- a/samples/org/easymock/samples/ExampleTest.java
+++ b/samples/org/easymock/samples/ExampleTest.java
@@ -1,116 +1,155 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.samples;
-
-import static org.easymock.EasyMock.aryEq;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import org.junit.Before;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-public class ExampleTest {
-
-    private ClassUnderTest classUnderTest;
-
-    private Collaborator mock;
-
-    @Before
-    public void setup() {
-        mock = createMock(Collaborator.class);
-        classUnderTest = new ClassUnderTest();
-        classUnderTest.addListener(mock);
-    }
-
-    @Test
-    public void removeNonExistingDocument() {
-        replay(mock);
-        classUnderTest.removeDocument("Does not exist");
-    }
-
-    @Test
-    public void addDocument() {
-        mock.documentAdded("New Document");
-        replay(mock);
-        classUnderTest.addDocument("New Document", new byte[0]);
-        verify(mock);
-    }
-
-    @Test
-    public void addAndChangeDocument() {
-        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);
-    }
-
-    @Test
-    public void voteForRemoval() {
-        // expect document addition
-        mock.documentAdded("Document");
-        // expect to be asked to vote, and vote for it
-        expect(mock.voteForRemoval("Document")).andReturn((byte) 42);
-        // expect document removal
-        mock.documentRemoved("Document");
-
-        replay(mock);
-        classUnderTest.addDocument("Document", new byte[0]);
-        assertTrue(classUnderTest.removeDocument("Document"));
-        verify(mock);
-    }
-
-    @Test
-    public void voteAgainstRemoval() {
-        // expect document addition
-        mock.documentAdded("Document");
-        // expect to be asked to vote, and vote against it
-        expect(mock.voteForRemoval("Document")).andReturn((byte) -42); // 
-        // document removal is *not* expected
-
-        replay(mock);
-        classUnderTest.addDocument("Document", new byte[0]);
-        assertFalse(classUnderTest.removeDocument("Document"));
-        verify(mock);
-    }
-
-    @Test
-    public void voteForRemovals() {
-        mock.documentAdded("Document 1");
-        mock.documentAdded("Document 2");
-        String[] documents = new String[] { "Document 1", "Document 2" };
-        expect(mock.voteForRemovals(aryEq(documents))).andReturn((byte) 42);
-        mock.documentRemoved("Document 1");
-        mock.documentRemoved("Document 2");
-        replay(mock);
-        classUnderTest.addDocument("Document 1", new byte[0]);
-        classUnderTest.addDocument("Document 2", new byte[0]);
-        assertTrue(classUnderTest.removeDocuments(new String[] { "Document 1",
-                "Document 2" }));
-        verify(mock);
-    }
-
-    @Test
-    public void voteAgainstRemovals() {
-        mock.documentAdded("Document 1");
-        mock.documentAdded("Document 2");
-        String[] documents = new String[] { "Document 1", "Document 2" };
-        expect(mock.voteForRemovals(aryEq(documents))).andReturn((byte) -42);
-        replay(mock);
-        classUnderTest.addDocument("Document 1", new byte[0]);
-        classUnderTest.addDocument("Document 2", new byte[0]);
-        assertFalse(classUnderTest.removeDocuments(new String[] { "Document 1",
-                "Document 2" }));
-        verify(mock);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.IAnswer;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ExampleTest {
+
+    private ClassTested classUnderTest;
+
+    private Collaborator mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(Collaborator.class);
+        classUnderTest = new ClassTested();
+        classUnderTest.setListener(mock);
+    }
+
+    @Test
+    public void removeNonExistingDocument() {
+        replay(mock);
+        classUnderTest.removeDocument("Does not exist");
+    }
+
+    @Test
+    public void addDocument() {
+        mock.documentAdded("New Document");
+        replay(mock);
+        classUnderTest.addDocument("New Document", new byte[0]);
+        verify(mock);
+    }
+
+    @Test
+    public void addAndChangeDocument() {
+        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);
+    }
+
+    @Test
+    public void voteForRemoval() {
+        // expect document addition
+        mock.documentAdded("Document");
+        // expect to be asked to vote, and vote for it
+        expect(mock.voteForRemoval("Document")).andReturn((byte) 42);
+        // expect document removal
+        mock.documentRemoved("Document");
+
+        replay(mock);
+        classUnderTest.addDocument("Document", new byte[0]);
+        assertTrue(classUnderTest.removeDocument("Document"));
+        verify(mock);
+    }
+
+    @Test
+    public void voteAgainstRemoval() {
+        // expect document addition
+        mock.documentAdded("Document");
+        // expect to be asked to vote, and vote against it
+        expect(mock.voteForRemoval("Document")).andReturn((byte) -42); // 
+        // document removal is *not* expected
+
+        replay(mock);
+        classUnderTest.addDocument("Document", new byte[0]);
+        assertFalse(classUnderTest.removeDocument("Document"));
+        verify(mock);
+    }
+
+    @Test
+    public void voteForRemovals() {
+        mock.documentAdded("Document 1");
+        mock.documentAdded("Document 2");
+        expect(mock.voteForRemovals("Document 1", "Document 2")).andReturn((byte) 42);
+        mock.documentRemoved("Document 1");
+        mock.documentRemoved("Document 2");
+        replay(mock);
+        classUnderTest.addDocument("Document 1", new byte[0]);
+        classUnderTest.addDocument("Document 2", new byte[0]);
+        assertTrue(classUnderTest.removeDocuments(new String[] { "Document 1", "Document 2" }));
+        verify(mock);
+    }
+
+    @Test
+    public void voteAgainstRemovals() {
+        mock.documentAdded("Document 1");
+        mock.documentAdded("Document 2");
+        expect(mock.voteForRemovals("Document 1", "Document 2")).andReturn((byte) -42);
+        replay(mock);
+        classUnderTest.addDocument("Document 1", new byte[0]);
+        classUnderTest.addDocument("Document 2", new byte[0]);
+        assertFalse(classUnderTest.removeDocuments("Document 1", "Document 2"));
+        verify(mock);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void answerVsDelegate() {
+        final 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>() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public String remove(final int index) {
+                return Integer.toString(index);
+            }
+        });
+
+        replay(l);
+
+        assertEquals("10", l.remove(10));
+        assertEquals("10", l.remove(10));
+
+        verify(l);
+    }
+}
diff --git a/samples/org/easymock/samples/PartialClassMockTest.java b/samples/org/easymock/samples/PartialClassMockTest.java
new file mode 100644
index 0000000..6de09fa
--- /dev/null
+++ b/samples/org/easymock/samples/PartialClassMockTest.java
@@ -0,0 +1,80 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.EasyMockSupport;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Example of how to perform partial mocking
+ * 
+ * @author Henri Tremblay
+ */
+public class PartialClassMockTest extends EasyMockSupport {
+
+    public static class Rect {
+
+        private int x;
+
+        private int y;
+
+        public int getX() {
+            return x;
+        }
+
+        public void setX(final int x) {
+            this.x = x;
+        }
+
+        public int getY() {
+            return y;
+        }
+
+        public void setY(final int y) {
+            this.y = y;
+        }
+
+        public int getArea() {
+            return getX() * getY();
+        }
+    }
+
+    private Rect rect;
+
+    @Before
+    public void setUp() throws Exception {
+        rect = createMockBuilder(Rect.class).addMockedMethods("getX", "getY").createMock();
+    }
+
+    @After
+    public void tearDown() {
+        rect = null;
+    }
+
+    @Test
+    public void testGetArea() {
+        expect(rect.getX()).andReturn(4);
+        expect(rect.getY()).andReturn(5);
+        replayAll();
+        assertEquals(20, rect.getArea());
+        verifyAll();
+    }
+}
diff --git a/samples/org/easymock/samples/SupportTest.java b/samples/org/easymock/samples/SupportTest.java
new file mode 100644
index 0000000..17f6e70
--- /dev/null
+++ b/samples/org/easymock/samples/SupportTest.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.EasyMockSupport;
+import org.easymock.IMocksControl;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class SupportTest extends EasyMockSupport {
+
+    private Collaborator collaborator;
+
+    private ClassTested classUnderTest;
+
+    @Before
+    public void setup() {
+        classUnderTest = new ClassTested();
+    }
+
+    @Test
+    public void addDocument() {
+        collaborator = createMock(Collaborator.class);
+        classUnderTest.setListener(collaborator);
+        collaborator.documentAdded("New Document");
+        replayAll();
+        classUnderTest.addDocument("New Document", new byte[0]);
+        verifyAll();
+    }
+
+    @Test
+    public void voteForRemovals() {
+
+        final IMocksControl ctrl = createControl();
+        collaborator = ctrl.createMock(Collaborator.class);
+        classUnderTest.setListener(collaborator);
+
+        collaborator.documentAdded("Document 1");
+
+        expect(collaborator.voteForRemovals("Document 1")).andReturn((byte) 20);
+
+        collaborator.documentRemoved("Document 1");
+
+        replayAll();
+
+        classUnderTest.addDocument("Document 1", new byte[0]);
+        assertTrue(classUnderTest.removeDocuments("Document 1"));
+
+        verifyAll();
+    }
+}
diff --git a/samples/org/easymock/samples/ThrowableEquals.java b/samples/org/easymock/samples/ThrowableEquals.java
index ed22071..2166bd3 100644
--- a/samples/org/easymock/samples/ThrowableEquals.java
+++ b/samples/org/easymock/samples/ThrowableEquals.java
@@ -1,40 +1,53 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.samples;
-
-import static org.easymock.EasyMock.reportMatcher;
-
-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("<");
-        buffer.append(expected.getClass().getName());
-        buffer.append(" with message \"");
-        buffer.append(expected.getMessage());
-        buffer.append("\">");
-
-    }
-
-    public static <T extends Throwable> T eqException(T in) {
-        reportMatcher(new ThrowableEquals(in));
-        return in;
-    }            
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.samples;
+
+import static org.easymock.EasyMock.*;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ThrowableEquals implements IArgumentMatcher {
+    private final Throwable expected;
+
+    public ThrowableEquals(final Throwable expected) {
+        this.expected = expected;
+    }
+
+    public boolean matches(final Object actual) {
+        if (!(actual instanceof Throwable)) {
+            return false;
+        }
+        final String actualMessage = ((Throwable) actual).getMessage();
+        return expected.getClass().equals(actual.getClass()) && expected.getMessage().equals(actualMessage);
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("<");
+        buffer.append(expected.getClass().getName());
+        buffer.append(" with message \"");
+        buffer.append(expected.getMessage());
+        buffer.append("\">");
+
+    }
+
+    public static <T extends Throwable> T eqException(final T in) {
+        reportMatcher(new ThrowableEquals(in));
+        return in;
+    }
+}
diff --git a/src/org/easymock/AbstractMatcher.java b/src/org/easymock/AbstractMatcher.java
deleted file mode 100644
index 4f47744..0000000
--- a/src/org/easymock/AbstractMatcher.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-import java.io.Serializable;
-
-/**
- * A convenience implementation of {@link ArgumentsMatcher}. A subclass that
- * does not redefine any method will behave like
- * {@link MockControl#EQUALS_MATCHER}.
- * 
- * @deprecated Since EasyMock 2.0, <code>ArgumentsMatcher</code>s are only supported
- * for the legacy <code>MockControl</code>. For mock objects generated by the methods
- * on <code>EasyMock</code>, there are per-argument matchers available. For more
- * information, see the EasyMock documentation.
- */
-public abstract class AbstractMatcher implements ArgumentsMatcher, Serializable {
-
-    private static final long serialVersionUID = -5463061331694985383L;
-
-    /**
-     * Checks whether an expected argument matches an actual argument; the method
-     * is used by
-     * {@link AbstractMatcher#matches(Object[], Object[])}. The arguments
-     * provided to this method are always not <code>null</code>.
-     * 
-     * @param expected
-     *            the expected argument.
-     * @param actual
-     *            the actual argument.
-     * @return true if the arguments match, false otherwise.
-     */
-    protected boolean argumentMatches(Object expected, Object actual) {
-        return expected.equals(actual);
-    }
-
-    /**
-     * Converts an argument to a String, used by
-     * {@link AbstractMatcher#toString(Object[])}.
-     * 
-     * @param argument
-     *            the argument to convert to a String.
-     * @return a <code>String</code> representation of the argument.
-     */
-    protected String argumentToString(Object argument) {
-        if (argument instanceof String) {
-            return "\"" + argument + "\"";
-        }
-        return "" + argument;
-    }
-
-    /**
-     * Checks whether an expected argument array matches an actual argument array.
-     * This convenience implementation uses
-     * <code>argumentMatches(Object, Object)</code> to check whether arguments
-     * pairs match. If all the arguments match, true is returned, otherwise
-     * false. In two cases, <code>argumentMatches(Object, Object)</code> is
-     * not called: If both argument arrays are null, they match; if one and only
-     * one is null, they do not match.
-     * 
-     * @param expected
-     *            the expected arguments.
-     * @param actual
-     *            the actual arguments.
-     * @return true if the arguments match, false otherwise.
-     */
-    public boolean matches(Object[] expected, Object[] actual) {
-        if (expected == actual) {
-            return true;
-        }
-        if (expected == null || actual == null) {
-            return false;
-        }
-        if (expected.length != actual.length) {
-            return false;
-        }
-        for (int i = 0; i < expected.length; i++) {
-            Object expectedObject = expected[i];
-            Object actualObject = actual[i];
-
-            if (expectedObject == null && actualObject == null) {
-                continue;
-            }
-
-            if (expectedObject == null && actualObject != null) {
-                return false;
-            }
-
-            if (expectedObject != null && actualObject == null) {
-                return false;
-            }
-
-            if (!argumentMatches(expectedObject, actualObject)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns a string representation of the matcher. This convenience
-     * implementation calls {@link AbstractMatcher#argumentToString(Object)}
-     * for every argument in the given array and returns the string representations
-     * of the arguments separated by commas.
-     * 
-     * @param arguments
-     *            the arguments to be used in the string representation.
-     * @return a string representation of the matcher.
-     */
-    public String toString(Object[] arguments) {
-        if (arguments == null)
-            arguments = new Object[0];
-
-        StringBuffer result = new StringBuffer();
-
-        for (int i = 0; i < arguments.length; i++) {
-            if (i > 0)
-                result.append(", ");
-            result.append(argumentToString(arguments[i]));
-        }
-        return result.toString();
-    }
-}
diff --git a/src/org/easymock/ArgumentsMatcher.java b/src/org/easymock/ArgumentsMatcher.java
deleted file mode 100644
index 428c8b2..0000000
--- a/src/org/easymock/ArgumentsMatcher.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-/**
- * A comparison function that is used to match arguments.
- * 
- * @see MockControl#setDefaultMatcher
- * @see MockControl#setMatcher
- * @see MockControl#EQUALS_MATCHER
- * @see MockControl#ARRAY_MATCHER
- * @see MockControl#ALWAYS_MATCHER
- * 
- * @deprecated Since EasyMock 2.0, <code>ArgumentsMatcher</code>s are only supported
- * for the legacy <code>MockControl</code>. For mock objects generated by the methods
- * on <code>EasyMock</code>, there are per-argument matchers available. For more
- * information, see the EasyMock documentation.
- */
-public interface ArgumentsMatcher {
-
-    /**
-     * Matches two arrays of arguments.
-     * 
-     * @param expected
-     *            the expected arguments.
-     * @param actual
-     *            the actual arguments.
-     * @return true if the arguments match, false otherwise.
-     */
-    boolean matches(Object[] expected, Object[] actual);
-
-    /**
-     * Returns a string representation of the arguments.
-     * 
-     * @param arguments
-     *            the arguments to be used in the string representation.
-     * @return a string representation of the arguments.
-     */
-    String toString(Object[] arguments);
-}
diff --git a/src/org/easymock/Capture.java b/src/org/easymock/Capture.java
index 6bfd6c2..a1bc5e2 100644
--- a/src/org/easymock/Capture.java
+++ b/src/org/easymock/Capture.java
@@ -1,67 +1,139 @@
-/*
- * Copyright (c) 2003-2008 OFFIS, Henri Tremblay. 
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-import java.io.Serializable;
-
-/**
- * Will contain what was captured by the <code>capture()</code> matcher. Knows if
- * something was captured or not (allows to capture a null value).
- *
- * @param <T> Type of the captured element
- */
-public class Capture<T> implements Serializable {
-
-    private static final long serialVersionUID = -4214363692271370781L;
-
-    private boolean captured = false;
-
-    private T value;
-
-    /**
-     * Will reset capture to a "nothing captured yet" state
-     */
-    public void reset() {
-        value = null;
-        captured = false;
-    }
-    
-    /**
-     * @return true if something was captured 
-     */
-    public boolean hasCaptured() {
-        return captured;
-    }
-
-    /**
-     * Return the captured value
-     * 
-     * @throws AssertionError if nothing was captured yet
-     * @return What was captured
-     */
-    public T getValue() {
-        if (!captured) {
-            throw new AssertionError("Nothing captured yet");
-        }
-        return value;
-    }
-
-    /**
-     * Used internally by the EasyMock framework to set the captured value
-     * @param value Value captured
-     */
-    public void setValue(T value) {
-        this.value = value;
-        this.captured = true;
-    }
-
-    @Override
-    public String toString() {
-        if (!captured) {
-            return "Nothing captured yet";
-        }
-        return value == null ? null : value.toString();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Will contain what was captured by the <code>capture()</code> matcher. Knows
+ * if something was captured or not (allows to capture a null value).
+ * 
+ * @param <T>
+ *            Type of the captured element
+ * 
+ * @author Henri Tremblay
+ */
+public class Capture<T> implements Serializable {
+
+    private static final long serialVersionUID = -4214363692271370781L;
+
+    private CaptureType type;
+
+    private final List<T> values = new ArrayList<T>(2);
+
+    /**
+     * Default constructor. Only the last element will be captured
+     */
+    public Capture() {
+        this(CaptureType.LAST);
+    }
+
+    /**
+     * Constructor allowing to select the capture type
+     * 
+     * @param type
+     *            capture type
+     */
+    public Capture(final CaptureType type) {
+        this.type = type;
+    }
+
+    /**
+     * Will reset capture to a "nothing captured yet" state
+     */
+    public void reset() {
+        values.clear();
+    }
+
+    /**
+     * @return true if something was captured
+     */
+    public boolean hasCaptured() {
+        return !values.isEmpty();
+    }
+
+    /**
+     * Return captured value
+     * 
+     * @throws AssertionError
+     *             if nothing was captured yet or if more than one value was
+     *             captured
+     * @return The last captured value
+     */
+    public T getValue() {
+        if (values.isEmpty()) {
+            throw new AssertionError("Nothing captured yet");
+        }
+        if (values.size() > 1) {
+            throw new AssertionError("More than one value captured: " + getValues());
+        }
+        return values.get(0);
+    }
+
+    /**
+     * Return all captured values. It returns the actual list so you can modify
+     * it's content if needed
+     * 
+     * @return The currently captured values
+     */
+    public List<T> getValues() {
+        return values;
+    }
+
+    /**
+     * Used internally by the EasyMock framework to add a new captured value
+     * 
+     * @param value
+     *            Value captured
+     */
+    public void setValue(final T value) {
+        switch (type) {
+        case NONE:
+            break;
+        case ALL:
+            values.add(value);
+            break;
+        case FIRST:
+            if (!hasCaptured()) {
+                values.add(value);
+            }
+            break;
+        case LAST:
+            if (hasCaptured()) {
+                reset();
+            }
+            values.add(value);
+            break;
+        // ///CLOVER:OFF
+        default:
+            throw new IllegalArgumentException("Unknown capture type: " + type);
+            // ///CLOVER:ON
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (values.isEmpty()) {
+            return "Nothing captured yet";
+        }
+        if (values.size() == 1) {
+            return String.valueOf(values.get(0));
+        }
+        return values.toString();
+    }
+}
diff --git a/src/org/easymock/CaptureType.java b/src/org/easymock/CaptureType.java
new file mode 100644
index 0000000..cf927e5
--- /dev/null
+++ b/src/org/easymock/CaptureType.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+/**
+ * Defines how arguments will be captured by a <tt>Capture</tt> object
+ * 
+ * @author Henri Tremblay
+ * @see Capture
+ */
+public enum CaptureType {
+    /**
+     * Do not capture anything
+     */
+    NONE,
+
+    /**
+     * Will capture the argument of the first matching call
+     */
+    FIRST,
+
+    /**
+     * Will capture the argument of the last matching call
+     */
+    LAST,
+
+    /**
+     * Will capture, in order, the arguments of each matching calls
+     */
+    ALL
+}
diff --git a/src/org/easymock/ConstructorArgs.java b/src/org/easymock/ConstructorArgs.java
new file mode 100644
index 0000000..5b6aabe
--- /dev/null
+++ b/src/org/easymock/ConstructorArgs.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+
+/**
+ * Class wrapping arguments to create a partial class mock that gets
+ * instantiated by calling one of its constructors
+ * 
+ * @author Henri Tremblay
+ */
+public class ConstructorArgs {
+
+    private final Constructor<?> constructor;
+
+    private final Object[] initArgs;
+
+    /**
+     * @param constructor
+     *            Constructor to be called when creating the mock
+     * @param initArgs
+     *            Arguments passed to the constructor
+     */
+    public ConstructorArgs(final Constructor<?> constructor, final Object... initArgs) {
+        this.constructor = constructor;
+        this.initArgs = initArgs;
+
+        validateArgs();
+    }
+
+    private void validateArgs() {
+
+        final Class<?>[] paramTypes = constructor.getParameterTypes();
+
+        if (initArgs.length != paramTypes.length) {
+            throw new IllegalArgumentException("Number of provided arguments doesn't match constructor ones");
+        }
+
+        for (int i = 0; i < initArgs.length; i++) {
+
+            final Class<?> paramType = paramTypes[i];
+            final Object arg = initArgs[i];
+
+            if (paramType.isPrimitive()) {
+                if (arg == null) {
+                    throw new IllegalArgumentException("Null argument for primitive param " + i);
+                }
+
+                try {
+                    final Field field = arg.getClass().getDeclaredField("TYPE");
+                    final Class<?> argType = (Class<?>) field.get(null);
+
+                    if (paramType.equals(argType)) {
+                        continue;
+                    }
+                } catch (final Exception e) {
+                    throw throwException(paramType, arg);
+                }
+
+                throw throwException(paramType, arg);
+            }
+            if (arg == null) {
+                continue;
+            }
+            if (!paramType.isAssignableFrom(arg.getClass())) {
+                throw throwException(paramType, arg);
+            }
+        }
+    }
+
+    private IllegalArgumentException throwException(final Class<?> paramType, final Object arg) {
+        return new IllegalArgumentException(arg + " isn't of type " + paramType);
+    }
+
+    /**
+     * @return arguments to be passed to the constructor
+     */
+    public Object[] getInitArgs() {
+        return initArgs;
+    }
+
+    /**
+     * @return constructor to be called
+     */
+    public Constructor<?> getConstructor() {
+        return constructor;
+    }
+}
diff --git a/src/org/easymock/EasyMock.java b/src/org/easymock/EasyMock.java
index 24c4d49..e7bc0e8 100644
--- a/src/org/easymock/EasyMock.java
+++ b/src/org/easymock/EasyMock.java
@@ -1,1632 +1,2196 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-import java.lang.reflect.Proxy;
-import java.util.Comparator;
-
-import org.easymock.internal.LastControl;
-import org.easymock.internal.MocksControl;
-import org.easymock.internal.ObjectMethodsFilter;
-import org.easymock.internal.matchers.*;
-
-public class EasyMock {
-
-    /**
-     * Creates a mock object that implements the given interface, order checking
-     * is enabled by default.
-     * 
-     * @param <T>
-     *            the interface that the mock object should implement.
-     * @param toMock
-     *            the class of the interface that the mock object should
-     *            implement.
-     * @return the mock object.
-     */
-    public static <T> T createStrictMock(Class<T> toMock) {
-        return createStrictControl().createMock(toMock);
-    }
-
-    /**
-     * Creates a mock object that implements the given interface, order checking
-     * is enabled by default.
-     * @param name the name of the mock object.     
-     * @param toMock
-     *            the class of the interface that the mock object should
-     *            implement.
-     * @param <T>
-     *            the interface that the mock object should implement.
-     * @return the mock object.
-     * @throws IllegalArgumentException if the name is not a valid Java identifier.
-     */
-    public static <T> T createStrictMock(String name, Class<T> toMock) {
-        return createStrictControl().createMock(name, toMock);
-    }
-
-    /**
-     * Creates a mock object that implements the given interface, order checking
-     * is disabled by default.
-     * 
-     * @param <T>
-     *            the interface that the mock object should implement.
-     * @param toMock
-     *            the class of the interface that the mock object should
-     *            implement.
-     * @return the mock object.
-     */
-    public static <T> T createMock(Class<T> toMock) {
-        return createControl().createMock(toMock);
-    }
-
-    /**
-     * Creates a mock object that implements the given interface, order checking
-     * is disabled by default.
-     * @param name the name of the mock object.
-     * @param toMock
-     *            the class of the interface that the mock object should
-     *            implement.
-     * 
-     * @param <T>
-     *            the interface that the mock object should implement.
-     * @return the mock object.
-     * @throws IllegalArgumentException if the name is not a valid Java identifier.
-     */
-    public static <T> T createMock(String name, Class<T> toMock) {
-        return createControl().createMock(name, toMock);
-    }
-    
-    /**
-     * Creates a mock object that implements the given interface, order checking
-     * is disabled by default, and the mock object will return <code>0</code>,
-     * <code>null</code> or <code>false</code> for unexpected invocations.
-     * 
-     * @param <T>
-     *            the interface that the mock object should implement.
-     * @param toMock
-     *            the class of the interface that the mock object should
-     *            implement.
-     * @return the mock object.
-     */
-    public static <T> T createNiceMock(Class<T> toMock) {
-        return createNiceControl().createMock(toMock);
-    }
-
-    /**
-     * Creates a mock object that implements the given interface, order checking
-     * is disabled by default, and the mock object will return <code>0</code>,
-     * <code>null</code> or <code>false</code> for unexpected invocations.
-     * @param name the name of the mock object.
-     * @param toMock
-     *            the class of the interface that the mock object should
-     *            implement.
-     * 
-     * @param <T>
-     *            the interface that the mock object should implement.
-     * @return the mock object.
-     * @throws IllegalArgumentException if the name is not a valid Java identifier.
-     */
-    public static <T> T createNiceMock(String name, Class<T> toMock) {
-        return createNiceControl().createMock(name, toMock);
-    }
-    
-    /**
-     * Creates a control, order checking is enabled by default.
-     * 
-     * @return the control.
-     */
-    public static IMocksControl createStrictControl() {
-        return new MocksControl(MocksControl.MockType.STRICT);
-    }
-
-    /**
-     * Creates a control, order checking is disabled by default.
-     * 
-     * @return the control.
-     */
-    public static IMocksControl createControl() {
-        return new MocksControl(MocksControl.MockType.DEFAULT);
-    }
-
-    /**
-     * Creates a control, order checking is disabled by default, and the mock
-     * objects created by this control will return <code>0</code>,
-     * <code>null</code> or <code>false</code> for unexpected invocations.
-     * 
-     * @return the control.
-     */
-    public static IMocksControl createNiceControl() {
-        return new MocksControl(MocksControl.MockType.NICE);
-    }
-
-    /**
-     * Returns the expectation setter for the last expected invocation in the
-     * current thread.
-     * 
-     * @param value
-     *            the parameter is used to transport the type to the
-     *            ExpectationSetter. It allows writing the expected call as
-     *            argument, i.e.
-     *            <code>expect(mock.getName()).andReturn("John Doe")<code>.
-     * 
-     * @return the expectation setter.
-     */
-    public static <T> IExpectationSetters<T> expect(T value) {
-        return EasyMock.getControlForLastCall();
-    }
-
-    /**
-     * Returns the expectation setter for the last expected invocation in the
-     * current thread. This method is used for expected invocations on void
-     * methods.
-     * 
-     * @return the expectation setter.
-     */
-    public static <T> IExpectationSetters<T> expectLastCall() {
-        return getControlForLastCall();
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T> IExpectationSetters<T> getControlForLastCall() {
-        MocksControl lastControl = LastControl.lastControl();
-        if (lastControl == null) {
-            throw new IllegalStateException("no last call on a mock available");
-        }
-        return (IExpectationSetters<T>) lastControl;
-    }
-
-    /**
-     * Expects any boolean argument. For details, see the EasyMock
-     * documentation.
-     * 
-     * @return <code>false</code>.
-     */
-    public static boolean anyBoolean() {
-        reportMatcher(Any.ANY);
-        return false;
-    }
-
-    /**
-     * Expects any byte argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static byte anyByte() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any char argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static char anyChar() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any int argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static int anyInt() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any long argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static long anyLong() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any float argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static float anyFloat() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any double argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static double anyDouble() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any short argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>0</code>.
-     */
-    public static short anyShort() {
-        reportMatcher(Any.ANY);
-        return 0;
-    }
-
-    /**
-     * Expects any Object argument. For details, see the EasyMock documentation.
-     * 
-     * @return <code>null</code>.
-     */
-    public static <T> T anyObject() {
-        reportMatcher(Any.ANY);
-        return null;
-    }
-
-    /**
-     * Expects a comparable argument greater than or equal the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T extends Comparable<T>> T geq(Comparable<T> value) {
-        reportMatcher(new GreaterOrEqual<T>(value));
-        return null;
-    }
-    
-    /**
-     * Expects a byte argument greater than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static byte geq(byte value) {
-        reportMatcher(new GreaterOrEqual<Byte>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a double argument greater than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static double geq(double value) {
-        reportMatcher(new GreaterOrEqual<Double>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a float argument greater than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static float geq(float value) {
-        reportMatcher(new GreaterOrEqual<Float>(value));
-        return 0;
-    }
-
-    /**
-     * Expects an int argument greater than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static int geq(int value) {
-        reportMatcher(new GreaterOrEqual<Integer>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a long argument greater than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static long geq(long value) {
-        reportMatcher(new GreaterOrEqual<Long>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a short argument greater than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static short geq(short value) {
-        reportMatcher(new GreaterOrEqual<Short>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a comparable argument less than or equal the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T extends Comparable<T>> T leq(Comparable<T> value) {
-        reportMatcher(new LessOrEqual<T>(value));
-        return null;
-    }
-     
-    /**
-     * Expects a byte argument less than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static byte leq(byte value) {
-        reportMatcher(new LessOrEqual<Byte>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a double argument less than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static double leq(double value) {
-        reportMatcher(new LessOrEqual<Double>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a float argument less than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static float leq(float value) {
-        reportMatcher(new LessOrEqual<Float>(value));
-        return 0;
-    }
-
-    /**
-     * Expects an int argument less than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static int leq(int value) {
-        reportMatcher(new LessOrEqual<Integer>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a long argument less than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static long leq(long value) {
-        reportMatcher(new LessOrEqual<Long>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a short argument less than or equal to the given value. For
-     * details, see the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static short leq(short value) {
-        reportMatcher(new LessOrEqual<Short>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a comparable argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T extends Comparable<T>> T gt(Comparable<T> value) {
-        reportMatcher(new GreaterThan<T>(value));
-        return null;
-    }
-    
-    /**
-     * Expects a byte argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static byte gt(byte value) {
-        reportMatcher(new GreaterThan<Byte>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a double argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static double gt(double value) {
-        reportMatcher(new GreaterThan<Double>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a float argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static float gt(float value) {
-        reportMatcher(new GreaterThan<Float>(value));
-        return 0;
-    }
-
-    /**
-     * Expects an int argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static int gt(int value) {
-        reportMatcher(new GreaterThan<Integer>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a long argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static long gt(long value) {
-        reportMatcher(new GreaterThan<Long>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a short argument greater than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static short gt(short value) {
-        reportMatcher(new GreaterThan<Short>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a comparable argument less than the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T extends Comparable<T>> T lt(Comparable<T> value) {
-        reportMatcher(new LessThan<T>(value));
-        return null;
-    }
-    
-    /**
-     * Expects a byte argument less than the given value. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static byte lt(byte value) {
-        reportMatcher(new LessThan<Byte>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a double argument less than the given value. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static double lt(double value) {
-        reportMatcher(new LessThan<Double>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a float argument less than the given value. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static float lt(float value) {
-        reportMatcher(new LessThan<Float>(value));
-        return 0;
-    }
-
-    /**
-     * Expects an int argument less than the given value. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static int lt(int value) {
-        reportMatcher(new LessThan<Integer>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a long argument less than the given value. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static long lt(long value) {
-        reportMatcher(new LessThan<Long>(value));
-        return 0;
-    }
-
-    /**
-     * Expects a short argument less than the given value. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static short lt(short value) {
-        reportMatcher(new LessThan<Short>(value));
-        return 0;
-    }
-
-    /**
-     * Expects an object implementing the given class. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param <T>
-     *            the accepted type.
-     * @param clazz
-     *            the class of the accepted type.
-     * @return <code>null</code>.
-     */
-    public static <T> T isA(Class<T> clazz) {
-        reportMatcher(new InstanceOf(clazz));
-        return null;
-    }
-
-    /**
-     * Expects a string that contains the given substring. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param substring
-     *            the substring.
-     * @return <code>null</code>.
-     */
-    public static String contains(String substring) {
-        reportMatcher(new Contains(substring));
-        return null;
-    }
-
-    /**
-     * Expects a boolean that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>false</code>.
-     */
-    public static boolean and(boolean first, boolean second) {
-        LastControl.reportAnd(2);
-        return false;
-    }
-
-    /**
-     * Expects a byte that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static byte and(byte first, byte second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects a char that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static char and(char first, char second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects a double that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static double and(double first, double second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects a float that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static float and(float first, float second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects an int that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static int and(int first, int second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects a long that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static long and(long first, long second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects a short that matches both given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static short and(short first, short second) {
-        LastControl.reportAnd(2);
-        return 0;
-    }
-
-    /**
-     * Expects an Object that matches both given expectations.
-     * 
-     * @param <T>
-     *            the type of the object, it is passed through to prevent casts.
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>null</code>.
-     */
-    public static <T> T and(T first, T second) {
-        LastControl.reportAnd(2);
-        return null;
-    }
-
-    /**
-     * Expects a boolean that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>false</code>.
-     */
-    public static boolean or(boolean first, boolean second) {
-        LastControl.reportOr(2);
-        return false;
-    }
-
-    /**
-     * Expects a byte that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static byte or(byte first, byte second) {
-        LastControl.reportOr(2);
-        return 0;
-    }
-
-    /**
-     * Expects a char that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static char or(char first, char second) {
-        LastControl.reportOr(2);
-        return 0;
-    }
-
-    /**
-     * Expects a double that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static double or(double first, double second) {
-        LastControl.reportOr(2);
-        return 0;
-    }
-
-    /**
-     * Expects a float that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static float or(float first, float second) {
-        LastControl.reportOr(2);
-        return 0;
-    }
-
-    /**
-     * Expects an int that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static int or(int first, int second) {
-        LastControl.reportOr(2);
-        return first;
-    }
-
-    /**
-     * Expects a long that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static long or(long first, long second) {
-        LastControl.reportOr(2);
-        return 0;
-    }
-
-    /**
-     * Expects a short that matches one of the given expectations.
-     * 
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>0</code>.
-     */
-    public static short or(short first, short second) {
-        LastControl.reportOr(2);
-        return 0;
-    }
-
-    /**
-     * Expects an Object that matches one of the given expectations.
-     * 
-     * @param <T>
-     *            the type of the object, it is passed through to prevent casts.
-     * @param first
-     *            placeholder for the first expectation.
-     * @param second
-     *            placeholder for the second expectation.
-     * @return <code>null</code>.
-     */
-    public static <T> T or(T first, T second) {
-        LastControl.reportOr(2);
-        return null;
-    }
-
-    /**
-     * Expects a boolean that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>false</code>.
-     */
-    public static boolean not(boolean first) {
-        LastControl.reportNot();
-        return false;
-    }
-
-    /**
-     * Expects a byte that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static byte not(byte first) {
-        LastControl.reportNot();
-        return 0;
-    }
-
-    /**
-     * Expects a char that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static char not(char first) {
-        LastControl.reportNot();
-        return 0;
-    }
-
-    /**
-     * Expects a double that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static double not(double first) {
-        LastControl.reportNot();
-        return 0;
-    }
-
-    /**
-     * Expects a float that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static float not(float first) {
-        LastControl.reportNot();
-        return first;
-    }
-
-    /**
-     * Expects an int that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static int not(int first) {
-        LastControl.reportNot();
-        return 0;
-    }
-
-    /**
-     * Expects a long that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static long not(long first) {
-        LastControl.reportNot();
-        return 0;
-    }
-
-    /**
-     * Expects a short that does not match the given expectation.
-     * 
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>0</code>.
-     */
-    public static short not(short first) {
-        LastControl.reportNot();
-        return 0;
-    }
-
-    /**
-     * Expects an Object that does not match the given expectation.
-     * 
-     * @param <T>
-     *            the type of the object, it is passed through to prevent casts.
-     * @param first
-     *            placeholder for the expectation.
-     * @return <code>null</code>.
-     */
-    public static <T> T not(T first) {
-        LastControl.reportNot();
-        return null;
-    }
-
-    /**
-     * Expects a boolean that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static boolean eq(boolean value) {
-        reportMatcher(new Equals(value));
-        return false;
-    }
-
-    /**
-     * Expects a byte that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static byte eq(byte value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects a char that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static char eq(char value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects a double that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static double eq(double value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects a float that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static float eq(float value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects an int that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static int eq(int value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects a long that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static long eq(long value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects a short that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    public static short eq(short value) {
-        reportMatcher(new Equals(value));
-        return 0;
-    }
-
-    /**
-     * Expects an Object that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T> T eq(T value) {
-        reportMatcher(new Equals(value));
-        return null;
-    }
-
-    /**
-     * Expects a boolean array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static boolean[] aryEq(boolean[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects a byte array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static byte[] aryEq(byte[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects a char array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static char[] aryEq(char[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects a double array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static double[] aryEq(double[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects a float array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static float[] aryEq(float[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects an int array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static int[] aryEq(int[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects a long array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static long[] aryEq(long[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects a short array that is equal to the given array, i.e. it has to
-     * have the same length, and each element has to be equal.
-     * 
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static short[] aryEq(short[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects an Object array that is equal to the given array, i.e. it has to
-     * have the same type, length, and each element has to be equal.
-     * 
-     * @param <T>
-     *            the type of the array, it is passed through to prevent casts.
-     * @param value
-     *            the given arry.
-     * @return <code>null</code>.
-     */
-    public static <T> T[] aryEq(T[] value) {
-        reportMatcher(new ArrayEquals(value));
-        return null;
-    }
-
-    /**
-     * Expects null.
-     * 
-     * @return <code>null</code>.
-     */
-    public static <T> T isNull() {
-        reportMatcher(Null.NULL);
-        return null;
-    }
-
-    /**
-     * Expects not null.
-     * 
-     * @return <code>null</code>.
-     */
-    public static <T> T notNull() {
-        reportMatcher(NotNull.NOT_NULL);
-        return null;
-    }
-
-    /**
-     * Expects a string that contains a substring that matches the given regular
-     * expression. For details, see the EasyMock documentation.
-     * 
-     * @param regex
-     *            the regular expression.
-     * @return <code>null</code>.
-     */
-    public static String find(String regex) {
-        reportMatcher(new Find(regex));
-        return null;
-    }
-
-    /**
-     * Expects a string that matches the given regular expression. For details,
-     * see the EasyMock documentation.
-     * 
-     * @param regex
-     *            the regular expression.
-     * @return <code>null</code>.
-     */
-    public static String matches(String regex) {
-        reportMatcher(new Matches(regex));
-        return null;
-    }
-
-    /**
-     * Expects a string that starts with the given prefix. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param prefix
-     *            the prefix.
-     * @return <code>null</code>.
-     */
-    public static String startsWith(String prefix) {
-        reportMatcher(new StartsWith(prefix));
-        return null;
-    }
-
-    /**
-     * Expects a string that ends with the given suffix. For details, see the
-     * EasyMock documentation.
-     * 
-     * @param suffix
-     *            the suffix.
-     * @return <code>null</code>.
-     */
-    public static String endsWith(String suffix) {
-        reportMatcher(new EndsWith(suffix));
-        return null;
-    }
-
-    /**
-     * Expects a double that has an absolute difference to the given value that
-     * is less than the given delta. For details, see the EasyMock
-     * documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @param delta
-     *            the given delta.
-     * @return <code>0</code>.
-     */
-    public static double eq(double value, double delta) {
-        reportMatcher(new EqualsWithDelta(value, delta));
-        return 0;
-    }
-
-    /**
-     * Expects a float that has an absolute difference to the given value that
-     * is less than the given delta. For details, see the EasyMock
-     * documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @param delta
-     *            the given delta.
-     * @return <code>0</code>.
-     */
-    public static float eq(float value, float delta) {
-        reportMatcher(new EqualsWithDelta(value, delta));
-        return 0;
-    }
-
-    /**
-     * Expects an Object that is the same as the given value. For details, see
-     * the EasyMock documentation.
-     * 
-     * @param <T>
-     *            the type of the object, it is passed through to prevent casts.
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T> T same(T value) {
-        reportMatcher(new Same(value));
-        return null;
-    }
-    
-    /**
-     * Expects a comparable argument equals to the given value according to their
-     * compareTo method. For details, see the EasMock documentation.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>null</code>.
-     */
-    public static <T extends Comparable<T>> T cmpEq(Comparable<T> value) {
-        reportMatcher(new CompareEqual<T>(value));
-        return null;
-    }
-    
-    /**
-     * Expects an argument that will be compared using the provided comparator.
-     * The following comparison will take place:
-     * <p>
-     * <code>comparator.compare(actual, expected) operator 0</code>
-     * </p>
-     * For details, see the EasyMock documentation.
-     * 
-     * @param value the given value.
-     * @param comparator Comparator used to compare the actual with expected value.
-     * @param operator The comparison operator.
-     * @return <code>null</code>
-     */
-    public static <T> T cmp(T value, Comparator<? super T> comparator, LogicalOperator operator) {
-        reportMatcher(new Compare<T>(value, comparator, operator));
-        return null;
-    }
-
-
-    /**
-     * Expects a byte that is equal to the given value.
-     * 
-     * @param value
-     *            the given value.
-     * @return <code>0</code>.
-     */
-    
-    
-    /**
-     * Expect any object but captures it for later use.
-     *  
-     * @param <T> Type of the captured object
-     * @param captured Where the parameter is captured
-     * @return <code>null</code>
-     */
-    public static <T> T capture(Capture<T> captured) {
-        reportMatcher(new Captures<T>(captured));
-        return null;
-    }
-    
-    /**
-     * Expect any int but captures it for later use.
-     *  
-     * @param captured Where the parameter is captured
-     * @return <code>0</code>
-     */
-    public static int capture(Capture<Integer> captured) {
-        reportMatcher(new Captures<Integer>(captured));
-        return 0;
-    }
-    
-    /**
-     * Expect any long but captures it for later use.
-     *  
-     * @param captured Where the parameter is captured
-     * @return <code>0</code>
-     */
-    public static long capture(Capture<Long> captured) {
-        reportMatcher(new Captures<Long>(captured));
-        return 0;
-    }
-    
-    /**
-     * Expect any float but captures it for later use.
-     *  
-     * @param captured Where the parameter is captured
-     * @return <code>0</code>
-     */
-    public static float capture(Capture<Float> captured) {
-        reportMatcher(new Captures<Float>(captured));
-        return 0;
-    }
-    
-    /**
-     * Expect any double but captures it for later use.
-     *  
-     * @param captured Where the parameter is captured
-     * @return <code>0</code>
-     */
-    public static double capture(Capture<Double> captured) {
-        reportMatcher(new Captures<Double>(captured));
-        return 0;
-    }
-
-    /**
-     * Expect any byte but captures it for later use.
-     *  
-     * @param captured Where the parameter is captured
-     * @return <code>0</code>
-     */
-    public static byte capture(Capture<Byte> captured) {
-        reportMatcher(new Captures<Byte>(captured));
-        return 0;
-    }
-    
-    /**
-     * Expect any char but captures it for later use.
-     *  
-     * @param captured Where the parameter is captured
-     * @return <code>0</code>
-     */
-    public static char capture(Capture<Character> captured) {
-        reportMatcher(new Captures<Character>(captured));
-        return 0;
-    }
-    
-    /**
-     * Switches the given mock objects (more exactly: the controls of the mock
-     * objects) to replay mode. For details, see the EasyMock documentation.
-     * 
-     * @param mocks
-     *            the mock objects.
-     */
-    public static void replay(Object... mocks) {
-        for (Object mock : mocks) {
-            getControl(mock).replay();
-        }
-    }
-
-    /**
-     * Resets the given mock objects (more exactly: the controls of the mock
-     * objects). For details, see the EasyMock documentation.
-     * 
-     * @param mocks
-     *            the mock objects.
-     */
-    public static void reset(Object... mocks) {
-        for (Object mock : mocks) {
-            getControl(mock).reset();
-        }
-    }
-
-    /**
-     * Resets the given mock objects (more exactly: the controls of the mock
-     * objects) and turn them to a mock with nice behavior. For details, see 
-     * the EasyMock documentation.
-     * 
-     * @param mocks
-     *            the mock objects
-     */
-    public static void resetToNice(Object... mocks) {
-        for (Object mock : mocks) {
-            getControl(mock).resetToNice();
-        }
-    }
-    
-    /**
-     * Resets the given mock objects (more exactly: the controls of the mock
-     * objects) and turn them to a mock with default behavior. For details, see 
-     * the EasyMock documentation.
-     * 
-     * @param mocks
-     *            the mock objects
-     */
-    public static void resetToDefault(Object... mocks) {
-        for (Object mock : mocks) {
-            getControl(mock).resetToDefault();
-        }
-    }
-    
-    /**
-     * Resets the given mock objects (more exactly: the controls of the mock
-     * objects) and turn them to a mock with strict behavior. For details, see 
-     * the EasyMock documentation.
-     * 
-     * @param mocks
-     *            the mock objects
-     */
-    public static void resetToStrict(Object... mocks) {
-        for (Object mock : mocks) {
-            getControl(mock).resetToStrict();
-        }
-    }
-    
-    /**
-     * Verifies the given mock objects (more exactly: the controls of the mock
-     * objects).
-     * 
-     * @param mocks
-     *            the mock objects.
-     */
-    public static void verify(Object... mocks) {
-        for (Object mock : mocks) {
-            getControl(mock).verify();
-        }
-    }
-
-    /**
-     * Switches order checking of the given mock object (more exactly: the
-     * control of the mock object) the on and off. For details, see the EasyMock
-     * documentation.
-     * 
-     * @param mock
-     *            the mock object.
-     * @param state
-     *            <code>true</code> switches order checking on,
-     *            <code>false</code> switches it off.
-     */
-    public static void checkOrder(Object mock, boolean state) {
-        getControl(mock).checkOrder(state);
-    }
-
-    /**
-     * Reports an argument matcher. This method is needed to define own argument
-     * matchers. For details, see the EasyMock documentation.
-     * 
-     * @param matcher
-     */
-    public static void reportMatcher(IArgumentMatcher matcher) {
-        LastControl.reportMatcher(matcher);
-    }
-
-    private static MocksControl getControl(Object mock) {
-        return ((ObjectMethodsFilter) Proxy
-        .getInvocationHandler(mock)).getDelegate().getControl();
-    }
-
-    /**
-     * Returns the arguments of the current mock method call, if inside an
-     * <code>IAnswer</code> callback - be careful here, reordering parameters of  
-     * method changes the semantics of your tests.
-     * 
-     * @return the arguments of the current mock method call.
-     * @throws IllegalStateException
-     *             if called outside of <code>IAnswer</code> callbacks.
-     */
-    public static Object[] getCurrentArguments() {
-        Object[] result = LastControl.getCurrentArguments();
-        if (result == null) {
-            throw new IllegalStateException(
-                    "current arguments are only available when executing callback methods");
-        }
-        return result;
-    }
-    
-    /**
-     * Makes the mock thread safe. The mock will be usable in a multithreaded
-     * environment.
-     * 
-     * @param mock the mock to make thread safe
-     * @param threadSafe If the mock should be thread safe or not
-     */
-    public static void makeThreadSafe(Object mock, boolean threadSafe) {
-        getControl(mock).makeThreadSafe(threadSafe);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+import org.easymock.internal.*;
+import org.easymock.internal.matchers.*;
+
+/**
+ * Main EasyMock class. Contains methods to create, replay and verify mocks and
+ * a list of standard matchers.
+ * 
+ * @author OFFIS, Tammo Freese
+ * @author Henri Tremblay
+ */
+public class EasyMock {
+
+    /**
+     * Since EasyMock 2.4, by default, a mock wasn't allowed to be called in
+     * multiple threads unless it was made thread-safe (See
+     * {@link #makeThreadSafe(Object, boolean)} method). Since EasyMock 2.5,
+     * this isn't the default anymore. For backward compatibility, this property
+     * can bring EasyMock 2.4 behavior back.
+     */
+    public static final String ENABLE_THREAD_SAFETY_CHECK_BY_DEFAULT = "easymock.enableThreadSafetyCheckByDefault";
+
+    /**
+     * Since EasyMock 2.5, by default a mock is thread-safe. For backward
+     * compatibility, this property can change the default. A given mock still
+     * can be made thread-safe by calling
+     * {@link #makeThreadSafe(Object, boolean)}.
+     */
+    public static final String NOT_THREAD_SAFE_BY_DEFAULT = "easymock.notThreadSafeByDefault";
+
+    /**
+     * Since EasyMock 3.0, EasyMock can perform class mocking directly without
+     * using the class extension. If you want to disable any class mocking, turn
+     * this to true.
+     */
+    public static final String DISABLE_CLASS_MOCKING = "easymock.disableClassMocking";
+
+    /**
+     * Creates a mock object, of the requested type, that implements the given interface
+     * or extends the given class
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param type 
+     *            the type of the mock to be created.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @return the mock object.
+     * @since 3.2
+     */
+    public static <T> T createMock(final MockType type, final Class<T> toMock) {
+        return createControl(type).createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object, of the requested type and name, that implements the given interface
+     * or extends the given class
+     * 
+     * @param <T> 
+     *            the class or interface that should be mocked.
+     * @param name 
+     *            the name of the mock object.
+     * @param type 
+     *            the type of the mock to be created.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @return the mock object.
+     * @since 3.2
+     */
+    public static <T> T createMock(final String name, final MockType type, final Class<T> toMock) {
+        return createControl(type).createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is enabled by default.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @return the mock object.
+     */
+    public static <T> T createStrictMock(final Class<T> toMock) {
+        return createStrictControl().createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is enabled by default.
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public static <T> T createStrictMock(final String name, final Class<T> toMock) {
+        return createStrictControl().createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @return the mock object.
+     */
+    public static <T> T createMock(final Class<T> toMock) {
+        return createControl().createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default.
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public static <T> T createMock(final String name, final Class<T> toMock) {
+        return createControl().createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @return the mock object.
+     */
+    public static <T> T createNiceMock(final Class<T> toMock) {
+        return createNiceControl().createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public static <T> T createNiceMock(final String name, final Class<T> toMock) {
+        return createNiceControl().createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createStrictMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createStrictControl().createMock(toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createStrictMock(final String name, final Class<T> toMock,
+            final Method... mockedMethods) {
+        return createStrictControl().createMock(name, toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createStrictMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createStrictControl().createMock(toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createStrictMock(final String name, final Class<T> toMock,
+            final ConstructorArgs constructorArgs, final Method... mockedMethods) {
+        return createStrictControl().createMock(name, toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createControl().createMock(toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createMock(final String name, final Class<T> toMock, final Method... mockedMethods) {
+        return createControl().createMock(name, toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createControl().createMock(toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createMock(final String name, final Class<T> toMock,
+            final ConstructorArgs constructorArgs, final Method... mockedMethods) {
+        return createControl().createMock(name, toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createNiceMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createNiceControl().createMock(toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createNiceMock(final String name, final Class<T> toMock,
+            final Method... mockedMethods) {
+        return createNiceControl().createMock(name, toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createNiceMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createNiceControl().createMock(toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class or interface that should be mocked.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public static <T> T createNiceMock(final String name, final Class<T> toMock,
+            final ConstructorArgs constructorArgs, final Method... mockedMethods) {
+        return createNiceControl().createMock(name, toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Create a mock builder allowing to create a partial mock for the given
+     * class or interface.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class or interface that should be mocked.
+     * @return a mock builder to create a partial mock
+     */
+    public static <T> IMockBuilder<T> createMockBuilder(final Class<T> toMock) {
+        return new MockBuilder<T>(toMock);
+    }
+
+    /**
+     * Creates a control of the requested type.
+     * 
+     * @param type the mock type
+     * @return the control.
+     * @since 3.2
+     */
+    public static IMocksControl createControl(final MockType type) {
+        return new MocksControl(type);
+    }
+
+    /**
+     * Creates a control, order checking is enabled by default.
+     * 
+     * @return the control.
+     */
+    public static IMocksControl createStrictControl() {
+        return createControl(MockType.STRICT);
+    }
+
+    /**
+     * Creates a control, order checking is disabled by default.
+     * 
+     * @return the control.
+     */
+    public static IMocksControl createControl() {
+        return createControl(MockType.DEFAULT);
+    }
+
+    /**
+     * Creates a control, order checking is disabled by default, and the mock
+     * objects created by this control will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @return the control.
+     */
+    public static IMocksControl createNiceControl() {
+        return createControl(MockType.NICE);
+    }
+
+    /**
+     * Returns the expectation setter for the last expected invocation in the
+     * current thread.
+     * 
+     * @param <T>
+     *            type returned by the expected method
+     * @param value
+     *            the parameter is used to transport the type to the
+     *            ExpectationSetter. It allows writing the expected call as
+     *            argument, i.e.
+     *            <code>expect(mock.getName()).andReturn("John Doe")<code>.
+     * 
+     * @return the expectation setter.
+     */
+    public static <T> IExpectationSetters<T> expect(final T value) {
+        return EasyMock.getControlForLastCall();
+    }
+
+    /**
+     * Returns the expectation setter for the last expected invocation in the
+     * current thread. This method is used for expected invocations on void
+     * methods.
+     * 
+     * @param <T>
+     *            type returned by the expected method
+     * @return the expectation setter.
+     */
+    public static <T> IExpectationSetters<T> expectLastCall() {
+        return getControlForLastCall();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> IExpectationSetters<T> getControlForLastCall() {
+        final MocksControl lastControl = LastControl.lastControl();
+        if (lastControl == null) {
+            LastControl.pullMatchers(); // cleanup matchers to prevent impacting
+            // other tests
+            throw new IllegalStateException("no last call on a mock available");
+        }
+        return (IExpectationSetters<T>) lastControl;
+    }
+
+    /**
+     * Expects any boolean argument. For details, see the EasyMock
+     * documentation.
+     * 
+     * @return <code>false</code>.
+     */
+    public static boolean anyBoolean() {
+        reportMatcher(Any.ANY);
+        return false;
+    }
+
+    /**
+     * Expects any byte argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static byte anyByte() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any char argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static char anyChar() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any int argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static int anyInt() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any long argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static long anyLong() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any float argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static float anyFloat() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any double argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static double anyDouble() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any short argument. For details, see the EasyMock documentation.
+     * 
+     * @return <code>0</code>.
+     */
+    public static short anyShort() {
+        reportMatcher(Any.ANY);
+        return 0;
+    }
+
+    /**
+     * Expects any Object argument. For details, see the EasyMock documentation.
+     * This matcher (and {@link #anyObject(Class)}) can be used in these three
+     * ways:
+     * <ul>
+     * <li><code>(T)EasyMock.anyObject() // explicit cast</code></li>
+     * <li>
+     * <code>EasyMock.<T> anyObject() // fixing the returned generic</code>
+     * </li>
+     * <li>
+     * <code>EasyMock.anyObject(T.class) // pass the returned type in parameter</code>
+     * </li>
+     * </ul>
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @return <code>null</code>.
+     */
+    public static <T> T anyObject() {
+        reportMatcher(Any.ANY);
+        return null;
+    }
+
+    /**
+     * Expects any Object argument. For details, see the EasyMock documentation.
+     * To work well with generics, this matcher can be used in three different
+     * ways. See {@link #anyObject()}.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param clazz
+     *            the class of the argument to match
+     * @return <code>null</code>.
+     */
+    public static <T> T anyObject(final Class<T> clazz) {
+        reportMatcher(Any.ANY);
+        return null;
+    }
+
+    /**
+     * Expect any string whatever its content is. Exactly the same as
+     * {@link #anyObject()} but prevents typing issues for the much used String
+     * type. Consider this method to be a syntactic sugar.
+     * 
+     * @return <code>null</code>.
+     */
+    public static String anyString() {
+        return anyObject();
+    }
+
+    /**
+     * Expects a comparable argument greater than or equal the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T extends Comparable<T>> T geq(final Comparable<T> value) {
+        reportMatcher(new GreaterOrEqual<T>(value));
+        return null;
+    }
+
+    /**
+     * Expects a byte argument greater than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static byte geq(final byte value) {
+        reportMatcher(new GreaterOrEqual<Byte>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a double argument greater than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static double geq(final double value) {
+        reportMatcher(new GreaterOrEqual<Double>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a float argument greater than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static float geq(final float value) {
+        reportMatcher(new GreaterOrEqual<Float>(value));
+        return 0;
+    }
+
+    /**
+     * Expects an int argument greater than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static int geq(final int value) {
+        reportMatcher(new GreaterOrEqual<Integer>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a long argument greater than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static long geq(final long value) {
+        reportMatcher(new GreaterOrEqual<Long>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a short argument greater than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static short geq(final short value) {
+        reportMatcher(new GreaterOrEqual<Short>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a comparable argument less than or equal the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T extends Comparable<T>> T leq(final Comparable<T> value) {
+        reportMatcher(new LessOrEqual<T>(value));
+        return null;
+    }
+
+    /**
+     * Expects a byte argument less than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static byte leq(final byte value) {
+        reportMatcher(new LessOrEqual<Byte>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a double argument less than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static double leq(final double value) {
+        reportMatcher(new LessOrEqual<Double>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a float argument less than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static float leq(final float value) {
+        reportMatcher(new LessOrEqual<Float>(value));
+        return 0;
+    }
+
+    /**
+     * Expects an int argument less than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static int leq(final int value) {
+        reportMatcher(new LessOrEqual<Integer>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a long argument less than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static long leq(final long value) {
+        reportMatcher(new LessOrEqual<Long>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a short argument less than or equal to the given value. For
+     * details, see the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static short leq(final short value) {
+        reportMatcher(new LessOrEqual<Short>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a comparable argument greater than the given value. For details,
+     * see the EasyMock documentation.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T extends Comparable<T>> T gt(final Comparable<T> value) {
+        reportMatcher(new GreaterThan<T>(value));
+        return null;
+    }
+
+    /**
+     * Expects a byte argument greater than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static byte gt(final byte value) {
+        reportMatcher(new GreaterThan<Byte>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a double argument greater than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static double gt(final double value) {
+        reportMatcher(new GreaterThan<Double>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a float argument greater than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static float gt(final float value) {
+        reportMatcher(new GreaterThan<Float>(value));
+        return 0;
+    }
+
+    /**
+     * Expects an int argument greater than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static int gt(final int value) {
+        reportMatcher(new GreaterThan<Integer>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a long argument greater than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static long gt(final long value) {
+        reportMatcher(new GreaterThan<Long>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a short argument greater than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static short gt(final short value) {
+        reportMatcher(new GreaterThan<Short>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a comparable argument less than the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T extends Comparable<T>> T lt(final Comparable<T> value) {
+        reportMatcher(new LessThan<T>(value));
+        return null;
+    }
+
+    /**
+     * Expects a byte argument less than the given value. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static byte lt(final byte value) {
+        reportMatcher(new LessThan<Byte>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a double argument less than the given value. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static double lt(final double value) {
+        reportMatcher(new LessThan<Double>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a float argument less than the given value. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static float lt(final float value) {
+        reportMatcher(new LessThan<Float>(value));
+        return 0;
+    }
+
+    /**
+     * Expects an int argument less than the given value. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static int lt(final int value) {
+        reportMatcher(new LessThan<Integer>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a long argument less than the given value. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static long lt(final long value) {
+        reportMatcher(new LessThan<Long>(value));
+        return 0;
+    }
+
+    /**
+     * Expects a short argument less than the given value. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static short lt(final short value) {
+        reportMatcher(new LessThan<Short>(value));
+        return 0;
+    }
+
+    /**
+     * Expects an object implementing the given class. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param <T>
+     *            the accepted type.
+     * @param clazz
+     *            the class of the accepted type.
+     * @return <code>null</code>.
+     */
+    public static <T> T isA(final Class<T> clazz) {
+        reportMatcher(new InstanceOf(clazz));
+        return null;
+    }
+
+    /**
+     * Expects a string that contains the given substring. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param substring
+     *            the substring.
+     * @return <code>null</code>.
+     */
+    public static String contains(final String substring) {
+        reportMatcher(new Contains(substring));
+        return null;
+    }
+
+    /**
+     * Expects a boolean that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>false</code>.
+     */
+    public static boolean and(final boolean first, final boolean second) {
+        LastControl.reportAnd(2);
+        return false;
+    }
+
+    /**
+     * Expects a byte that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static byte and(final byte first, final byte second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects a char that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static char and(final char first, final char second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects a double that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static double and(final double first, final double second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects a float that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static float and(final float first, final float second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects an int that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static int and(final int first, final int second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects a long that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static long and(final long first, final long second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects a short that matches both given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static short and(final short first, final short second) {
+        LastControl.reportAnd(2);
+        return 0;
+    }
+
+    /**
+     * Expects an Object that matches both given expectations.
+     * 
+     * @param <T>
+     *            the type of the object, it is passed through to prevent casts.
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>null</code>.
+     */
+    public static <T> T and(final T first, final T second) {
+        LastControl.reportAnd(2);
+        return null;
+    }
+
+    /**
+     * Expects a boolean that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>false</code>.
+     */
+    public static boolean or(final boolean first, final boolean second) {
+        LastControl.reportOr(2);
+        return false;
+    }
+
+    /**
+     * Expects a byte that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static byte or(final byte first, final byte second) {
+        LastControl.reportOr(2);
+        return 0;
+    }
+
+    /**
+     * Expects a char that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static char or(final char first, final char second) {
+        LastControl.reportOr(2);
+        return 0;
+    }
+
+    /**
+     * Expects a double that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static double or(final double first, final double second) {
+        LastControl.reportOr(2);
+        return 0;
+    }
+
+    /**
+     * Expects a float that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static float or(final float first, final float second) {
+        LastControl.reportOr(2);
+        return 0;
+    }
+
+    /**
+     * Expects an int that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static int or(final int first, final int second) {
+        LastControl.reportOr(2);
+        return first;
+    }
+
+    /**
+     * Expects a long that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static long or(final long first, final long second) {
+        LastControl.reportOr(2);
+        return 0;
+    }
+
+    /**
+     * Expects a short that matches one of the given expectations.
+     * 
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>0</code>.
+     */
+    public static short or(final short first, final short second) {
+        LastControl.reportOr(2);
+        return 0;
+    }
+
+    /**
+     * Expects an Object that matches one of the given expectations.
+     * 
+     * @param <T>
+     *            the type of the object, it is passed through to prevent casts.
+     * @param first
+     *            placeholder for the first expectation.
+     * @param second
+     *            placeholder for the second expectation.
+     * @return <code>null</code>.
+     */
+    public static <T> T or(final T first, final T second) {
+        LastControl.reportOr(2);
+        return null;
+    }
+
+    /**
+     * Expects a boolean that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>false</code>.
+     */
+    public static boolean not(final boolean first) {
+        LastControl.reportNot();
+        return false;
+    }
+
+    /**
+     * Expects a byte that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static byte not(final byte first) {
+        LastControl.reportNot();
+        return 0;
+    }
+
+    /**
+     * Expects a char that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static char not(final char first) {
+        LastControl.reportNot();
+        return 0;
+    }
+
+    /**
+     * Expects a double that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static double not(final double first) {
+        LastControl.reportNot();
+        return 0;
+    }
+
+    /**
+     * Expects a float that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static float not(final float first) {
+        LastControl.reportNot();
+        return first;
+    }
+
+    /**
+     * Expects an int that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static int not(final int first) {
+        LastControl.reportNot();
+        return 0;
+    }
+
+    /**
+     * Expects a long that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static long not(final long first) {
+        LastControl.reportNot();
+        return 0;
+    }
+
+    /**
+     * Expects a short that does not match the given expectation.
+     * 
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>0</code>.
+     */
+    public static short not(final short first) {
+        LastControl.reportNot();
+        return 0;
+    }
+
+    /**
+     * Expects an Object that does not match the given expectation.
+     * 
+     * @param <T>
+     *            the type of the object, it is passed through to prevent casts.
+     * @param first
+     *            placeholder for the expectation.
+     * @return <code>null</code>.
+     */
+    public static <T> T not(final T first) {
+        LastControl.reportNot();
+        return null;
+    }
+
+    /**
+     * Expects a boolean that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static boolean eq(final boolean value) {
+        reportMatcher(new Equals(value));
+        return false;
+    }
+
+    /**
+     * Expects a byte that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static byte eq(final byte value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects a char that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static char eq(final char value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects a double that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static double eq(final double value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects a float that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static float eq(final float value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects an int that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static int eq(final int value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects a long that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static long eq(final long value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects a short that is equal to the given value.
+     * 
+     * @param value
+     *            the given value.
+     * @return <code>0</code>.
+     */
+    public static short eq(final short value) {
+        reportMatcher(new Equals(value));
+        return 0;
+    }
+
+    /**
+     * Expects an Object that is equal to the given value.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T> T eq(final T value) {
+        reportMatcher(new Equals(value));
+        return null;
+    }
+
+    /**
+     * Expects a boolean array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static boolean[] aryEq(final boolean[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects a byte array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static byte[] aryEq(final byte[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects a char array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static char[] aryEq(final char[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects a double array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static double[] aryEq(final double[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects a float array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static float[] aryEq(final float[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects an int array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static int[] aryEq(final int[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects a long array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static long[] aryEq(final long[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects a short array that is equal to the given array, i.e. it has to
+     * have the same length, and each element has to be equal.
+     * 
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static short[] aryEq(final short[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects an Object array that is equal to the given array, i.e. it has to
+     * have the same type, length, and each element has to be equal.
+     * 
+     * @param <T>
+     *            the type of the array, it is passed through to prevent casts.
+     * @param value
+     *            the given array.
+     * @return <code>null</code>.
+     */
+    public static <T> T[] aryEq(final T[] value) {
+        reportMatcher(new ArrayEquals(value));
+        return null;
+    }
+
+    /**
+     * Expects null. To work well with generics, this matcher (and
+     * {@link #isNull(Class)}) can be used in these three ways:
+     * <ul>
+     * <li><code>(T)EasyMock.isNull() // explicit cast</code></li>
+     * <li>
+     * <code>EasyMock.<T> isNull() // fixing the returned generic</code></li>
+     * <li>
+     * <code>EasyMock.isNull(T.class) // pass the returned type in parameter</code>
+     * </li>
+     * </ul>
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @return <code>null</code>.
+     */
+    public static <T> T isNull() {
+        reportMatcher(Null.NULL);
+        return null;
+    }
+
+    /**
+     * Expects null. To work well with generics, this matcher can be used in
+     * three different ways. See {@link #isNull()}.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param clazz
+     *            the class of the argument to match
+     * @return <code>null</code>.
+     * 
+     * @see #isNull()
+     */
+    public static <T> T isNull(final Class<T> clazz) {
+        reportMatcher(Null.NULL);
+        return null;
+    }
+
+    /**
+     * Expects not null. To work well with generics, this matcher (and
+     * {@link #notNull(Class)}) can be used in these three ways:
+     * <ul>
+     * <li><code>(T)EasyMock.notNull() // explicit cast</code></li>
+     * <li>
+     * <code>EasyMock.<T> notNull() // fixing the returned generic</code></li>
+     * <li>
+     * <code>EasyMock.notNull(T.class) // pass the returned type in parameter</code>
+     * </li>
+     * </ul>
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @return <code>null</code>.
+     */
+    public static <T> T notNull() {
+        reportMatcher(NotNull.NOT_NULL);
+        return null;
+    }
+
+    /**
+     * Expects not null. To work well with generics, this matcher can be used in
+     * three different ways. See {@link #notNull()}.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param clazz
+     *            the class of the argument to match
+     * @return <code>null</code>.
+     * 
+     * @see #notNull()
+     */
+    public static <T> T notNull(final Class<T> clazz) {
+        reportMatcher(NotNull.NOT_NULL);
+        return null;
+    }
+
+    /**
+     * Expects a string that contains a substring that matches the given regular
+     * expression. For details, see the EasyMock documentation.
+     * 
+     * @param regex
+     *            the regular expression.
+     * @return <code>null</code>.
+     */
+    public static String find(final String regex) {
+        reportMatcher(new Find(regex));
+        return null;
+    }
+
+    /**
+     * Expects a string that matches the given regular expression. For details,
+     * see the EasyMock documentation.
+     * 
+     * @param regex
+     *            the regular expression.
+     * @return <code>null</code>.
+     */
+    public static String matches(final String regex) {
+        reportMatcher(new Matches(regex));
+        return null;
+    }
+
+    /**
+     * Expects a string that starts with the given prefix. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param prefix
+     *            the prefix.
+     * @return <code>null</code>.
+     */
+    public static String startsWith(final String prefix) {
+        reportMatcher(new StartsWith(prefix));
+        return null;
+    }
+
+    /**
+     * Expects a string that ends with the given suffix. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param suffix
+     *            the suffix.
+     * @return <code>null</code>.
+     */
+    public static String endsWith(final String suffix) {
+        reportMatcher(new EndsWith(suffix));
+        return null;
+    }
+
+    /**
+     * Expects a double that has an absolute difference to the given value that
+     * is less than the given delta. For details, see the EasyMock
+     * documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @param delta
+     *            the given delta.
+     * @return <code>0</code>.
+     */
+    public static double eq(final double value, final double delta) {
+        reportMatcher(new EqualsWithDelta(value, delta));
+        return 0;
+    }
+
+    /**
+     * Expects a float that has an absolute difference to the given value that
+     * is less than the given delta. For details, see the EasyMock
+     * documentation.
+     * 
+     * @param value
+     *            the given value.
+     * @param delta
+     *            the given delta.
+     * @return <code>0</code>.
+     */
+    public static float eq(final float value, final float delta) {
+        reportMatcher(new EqualsWithDelta(value, delta));
+        return 0;
+    }
+
+    /**
+     * Expects an Object that is the same as the given value. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param <T>
+     *            the type of the object, it is passed through to prevent casts.
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T> T same(final T value) {
+        reportMatcher(new Same(value));
+        return null;
+    }
+
+    /**
+     * Expects a comparable argument equals to the given value according to
+     * their compareTo method. For details, see the EasMock documentation.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @return <code>null</code>.
+     */
+    public static <T extends Comparable<T>> T cmpEq(final Comparable<T> value) {
+        reportMatcher(new CompareEqual<T>(value));
+        return null;
+    }
+
+    /**
+     * Expects an argument that will be compared using the provided comparator.
+     * The following comparison will take place:
+     * <p>
+     * <code>comparator.compare(actual, expected) operator 0</code>
+     * </p>
+     * For details, see the EasyMock documentation.
+     * 
+     * @param <T>
+     *            type of the method argument to match
+     * @param value
+     *            the given value.
+     * @param comparator
+     *            Comparator used to compare the actual with expected value.
+     * @param operator
+     *            The comparison operator.
+     * @return <code>null</code>
+     */
+    public static <T> T cmp(final T value, final Comparator<? super T> comparator,
+            final LogicalOperator operator) {
+        reportMatcher(new Compare<T>(value, comparator, operator));
+        return null;
+    }
+
+    /**
+     * Expect any object but captures it for later use.
+     * 
+     * @param <T>
+     *            Type of the captured object
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>null</code>
+     */
+    public static <T> T capture(final Capture<T> captured) {
+        reportMatcher(new Captures<T>(captured));
+        return null;
+    }
+
+    /**
+     * Expect any boolean but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>false</code>
+     */
+    public static boolean captureBoolean(final Capture<Boolean> captured) {
+        reportMatcher(new Captures<Boolean>(captured));
+        return false;
+    }
+
+    /**
+     * Expect any int but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>0</code>
+     */
+    public static int captureInt(final Capture<Integer> captured) {
+        reportMatcher(new Captures<Integer>(captured));
+        return 0;
+    }
+
+    /**
+     * Expect any long but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>0</code>
+     */
+    public static long captureLong(final Capture<Long> captured) {
+        reportMatcher(new Captures<Long>(captured));
+        return 0;
+    }
+
+    /**
+     * Expect any float but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>0</code>
+     */
+    public static float captureFloat(final Capture<Float> captured) {
+        reportMatcher(new Captures<Float>(captured));
+        return 0;
+    }
+
+    /**
+     * Expect any double but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>0</code>
+     */
+    public static double captureDouble(final Capture<Double> captured) {
+        reportMatcher(new Captures<Double>(captured));
+        return 0;
+    }
+
+    /**
+     * Expect any byte but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>0</code>
+     */
+    public static byte captureByte(final Capture<Byte> captured) {
+        reportMatcher(new Captures<Byte>(captured));
+        return 0;
+    }
+
+    /**
+     * Expect any char but captures it for later use.
+     * 
+     * @param captured
+     *            Where the parameter is captured
+     * @return <code>0</code>
+     */
+    public static char captureChar(final Capture<Character> captured) {
+        reportMatcher(new Captures<Character>(captured));
+        return 0;
+    }
+
+    /**
+     * Switches the given mock objects (more exactly: the controls of the mock
+     * objects) to replay mode. For details, see the EasyMock documentation.
+     * 
+     * @param mocks
+     *            the mock objects.
+     */
+    public static void replay(final Object... mocks) {
+        for (final Object mock : mocks) {
+            getControl(mock).replay();
+        }
+    }
+
+    /**
+     * Resets the given mock objects (more exactly: the controls of the mock
+     * objects). For details, see the EasyMock documentation.
+     * 
+     * @param mocks
+     *            the mock objects.
+     */
+    public static void reset(final Object... mocks) {
+        for (final Object mock : mocks) {
+            getControl(mock).reset();
+        }
+    }
+
+    /**
+     * Resets the given mock objects (more exactly: the controls of the mock
+     * objects) and turn them to a mock with nice behavior. For details, see the
+     * EasyMock documentation.
+     * 
+     * @param mocks
+     *            the mock objects
+     */
+    public static void resetToNice(final Object... mocks) {
+        for (final Object mock : mocks) {
+            getControl(mock).resetToNice();
+        }
+    }
+
+    /**
+     * Resets the given mock objects (more exactly: the controls of the mock
+     * objects) and turn them to a mock with default behavior. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param mocks
+     *            the mock objects
+     */
+    public static void resetToDefault(final Object... mocks) {
+        for (final Object mock : mocks) {
+            getControl(mock).resetToDefault();
+        }
+    }
+
+    /**
+     * Resets the given mock objects (more exactly: the controls of the mock
+     * objects) and turn them to a mock with strict behavior. For details, see
+     * the EasyMock documentation.
+     * 
+     * @param mocks
+     *            the mock objects
+     */
+    public static void resetToStrict(final Object... mocks) {
+        for (final Object mock : mocks) {
+            getControl(mock).resetToStrict();
+        }
+    }
+
+    /**
+     * Verifies the given mock objects (more exactly: the controls of the mock
+     * objects).
+     * 
+     * @param mocks
+     *            the mock objects.
+     */
+    public static void verify(final Object... mocks) {
+        for (final Object mock : mocks) {
+            getControl(mock).verify();
+        }
+    }
+
+    /**
+     * Switches order checking of the given mock object (more exactly: the
+     * control of the mock object) the on and off. For details, see the EasyMock
+     * documentation.
+     * 
+     * @param mock
+     *            the mock object.
+     * @param state
+     *            <code>true</code> switches order checking on,
+     *            <code>false</code> switches it off.
+     */
+    public static void checkOrder(final Object mock, final boolean state) {
+        getControl(mock).checkOrder(state);
+    }
+
+    /**
+     * Reports an argument matcher. This method is needed to define own argument
+     * matchers. For details, see the EasyMock documentation.
+     * 
+     * @param matcher
+     */
+    public static void reportMatcher(final IArgumentMatcher matcher) {
+        LastControl.reportMatcher(matcher);
+    }
+
+    private static MocksControl getControl(final Object mock) {
+        return MocksControl.getControl(mock);
+    }
+
+    /**
+     * Returns the arguments of the current mock method call, if inside an
+     * <code>IAnswer</code> callback - be careful here, reordering parameters of
+     * method changes the semantics of your tests.
+     * 
+     * @return the arguments of the current mock method call.
+     * @throws IllegalStateException
+     *             if called outside of <code>IAnswer</code> callbacks.
+     */
+    public static Object[] getCurrentArguments() {
+        final Invocation result = LastControl.getCurrentInvocation();
+        if (result == null) {
+            throw new IllegalStateException(
+                    "current arguments are only available when executing callback methods");
+        }
+        return result.getArguments();
+    }
+
+    /**
+     * By default, a mock is thread safe (unless
+     * {@link #NOT_THREAD_SAFE_BY_DEFAULT} is set). This method can change this
+     * behavior. Two reasons are known for someone to do that: Performance or
+     * dead-locking issues.
+     * 
+     * @param mock
+     *            the mock to make thread safe
+     * @param threadSafe
+     *            If the mock should be thread safe or not
+     */
+    public static void makeThreadSafe(final Object mock, final boolean threadSafe) {
+        getControl(mock).makeThreadSafe(threadSafe);
+    }
+
+    /**
+     * Tell that the mock should be used in only one thread. An exception will
+     * be thrown if that's not the case. This can be useful when mocking an
+     * object that isn't thread safe to make sure it is used correctly in a
+     * multithreaded environment. By default, no check is done unless
+     * {@link #ENABLE_THREAD_SAFETY_CHECK_BY_DEFAULT} was set to true.
+     * 
+     * @param mock
+     *            the mock
+     * @param shouldBeUsedInOneThread
+     *            If the mock should be used in only one thread
+     */
+    public static void checkIsUsedInOneThread(final Object mock, final boolean shouldBeUsedInOneThread) {
+        getControl(mock).checkIsUsedInOneThread(shouldBeUsedInOneThread);
+    }
+
+    /**
+     * Get the current value for an EasyMock property
+     * 
+     * @param key
+     *            key for the property
+     * @return the property value
+     */
+    public static String getEasyMockProperty(final String key) {
+        return EasyMockProperties.getInstance().getProperty(key);
+    }
+
+    /**
+     * Set a property to modify the default EasyMock behavior. These properties
+     * can also be set as System properties or in easymock.properties. This
+     * method can then be called to overload them. For details and a list of
+     * available properties see the EasyMock documentation.
+     * <p>
+     * <b>Note:</b> This method is static. Setting a property will change the
+     * entire EasyMock behavior.
+     * 
+     * @param key
+     *            property key
+     * @param value
+     *            property value. A null value will remove the property
+     * @return the previous property value
+     */
+    public static String setEasyMockProperty(final String key, final String value) {
+        return EasyMockProperties.getInstance().setProperty(key, value);
+    }
+
+    // ///CLOVER:OFF
+    protected EasyMock() { // Need to be protected since the Class extension extends it
+    }
+    // ///CLOVER:ON
+}
diff --git a/src/org/easymock/EasyMockRunner.java b/src/org/easymock/EasyMockRunner.java
new file mode 100644
index 0000000..0911c4b
--- /dev/null
+++ b/src/org/easymock/EasyMockRunner.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+/**
+ * JUnit runner used to process {@link Mock} and {@link TestSubject} annotations
+ * 
+ * @author Henri Tremblay
+ * @since 3.2
+ */
+public class EasyMockRunner extends BlockJUnit4ClassRunner {
+
+    public EasyMockRunner(final Class<?> klass) throws InitializationError {
+        super(klass);
+    }
+
+    @Override
+    protected Statement methodInvoker(final FrameworkMethod method, final Object test) {
+        return new EasyMockStatement(super.methodInvoker(method, test), test);
+    }
+
+}
+
+class EasyMockStatement extends Statement {
+
+    private final Statement originalStatement;
+
+    private final Object test;
+
+    public EasyMockStatement(final Statement originalStatement, final Object test) {
+        this.originalStatement = originalStatement;
+        this.test = test;
+    }
+
+    @Override
+    public void evaluate() throws Throwable {
+        EasyMockSupport.injectMocks(test);
+        originalStatement.evaluate();
+    }
+}
diff --git a/src/org/easymock/EasyMockSupport.java b/src/org/easymock/EasyMockSupport.java
new file mode 100644
index 0000000..ed483c4
--- /dev/null
+++ b/src/org/easymock/EasyMockSupport.java
@@ -0,0 +1,728 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.internal.MockBuilder;
+
+/**
+ * Helper class to be used to keep tracks of mocks easily. See EasyMock
+ * documentation and SupportTest sample.
+ * <p>
+ * Example of usage:
+ * 
+ * <pre>
+ * public class SupportTest extends EasyMockSupport {
+ *     @Test
+ *     public void test() {
+ *         firstMock = createMock(A.class);
+ *         secondMock = createMock(B.class);
+ *         
+ *         replayAll(); // put both mocks in replay mode
+ *         
+ *         // ... use mocks ..
+ *         
+ *         verifyAll(); // verify both mocks
+ *     }
+ * }
+ * </pre>
+ * 
+ * @author Henri Tremblay
+ */
+public class EasyMockSupport {
+
+    /** List of all controls created */
+    protected final List<IMocksControl> controls = new ArrayList<IMocksControl>(5);
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createStrictMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createStrictControl().createMock(toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createStrictMock(final String name, final Class<T> toMock, final Method... mockedMethods) {
+        return createStrictControl().createMock(name, toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createStrictMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createStrictControl().createMock(toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * enabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createStrictMock(final String name, final Class<T> toMock,
+            final ConstructorArgs constructorArgs, final Method... mockedMethods) {
+        return createStrictControl().createMock(name, toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createControl().createMock(toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createMock(final String name, final Class<T> toMock, final Method... mockedMethods) {
+        return createControl().createMock(name, toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createControl().createMock(toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createMock(final String name, final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createControl().createMock(name, toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createNiceMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createNiceControl().createMock(toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createNiceMock(final String name, final Class<T> toMock, final Method... mockedMethods) {
+        return createNiceControl().createMock(name, toMock, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createNiceMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createNiceControl().createMock(toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object that extends the given class, order checking is
+     * disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link #createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    public <T> T createNiceMock(final String name, final Class<T> toMock,
+            final ConstructorArgs constructorArgs, final Method... mockedMethods) {
+        return createNiceControl().createMock(name, toMock, constructorArgs, mockedMethods);
+    }
+
+    /**
+     * Creates a mock object of the requested type that implements the given interface or extends
+     * the given class
+     * 
+     * @param type
+     *            the type of the mock to be created.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public <T> T createMock(final MockType type, final Class<T> toMock) {
+        return createControl(type).createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object of the requested type that implements the given interface or extends
+     * the given class
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param type
+     *            the type of the mock to be created.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public <T> T createMock(final String name, final MockType type, final Class<T> toMock) {
+        return createControl(type).createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is enabled by default.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @return the mock object.
+     */
+    public <T> T createStrictMock(final Class<T> toMock) {
+        return createStrictControl().createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is enabled by default.
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public <T> T createStrictMock(final String name, final Class<T> toMock) {
+        return createStrictControl().createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @return the mock object.
+     */
+    public <T> T createMock(final Class<T> toMock) {
+        return createControl().createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default.
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public <T> T createMock(final String name, final Class<T> toMock) {
+        return createControl().createMock(name, toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @return the mock object.
+     */
+    public <T> T createNiceMock(final Class<T> toMock) {
+        return createNiceControl().createMock(toMock);
+    }
+
+    /**
+     * Creates a mock object that implements the given interface, order checking
+     * is disabled by default, and the mock object will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    public <T> T createNiceMock(final String name, final Class<T> toMock) {
+        return createNiceControl().createMock(name, toMock);
+    }
+
+    /**
+     * Creates a control, order checking is enabled by default.
+     * 
+     * @return the control.
+     */
+    public IMocksControl createStrictControl() {
+        final IMocksControl ctrl = EasyMock.createStrictControl();
+        controls.add(ctrl);
+        return ctrl;
+    }
+
+    /**
+     * Create a mock builder allowing to create a partial mock for the given
+     * class or interface.
+     * 
+     * @param <T>
+     *            the interface that the mock object should implement.
+     * @param toMock
+     *            the class of the interface that the mock object should
+     *            implement.
+     * @return a mock builder to create a partial mock
+     */
+    public <T> IMockBuilder<T> createMockBuilder(final Class<T> toMock) {
+        return new MockBuilder<T>(toMock, this);
+    }
+
+    /**
+     * Creates a control of the given type.
+     * 
+     * @param type the mock type.
+     * @return the control.
+     * @since 3.2
+     */
+    public IMocksControl createControl(final MockType type) {
+        final IMocksControl ctrl = EasyMock.createControl(type);
+        controls.add(ctrl);
+        return ctrl;
+    }
+
+    /**
+     * Creates a control, order checking is disabled by default.
+     * 
+     * @return the control.
+     */
+    public IMocksControl createControl() {
+        return createControl(MockType.DEFAULT);
+    }
+
+    /**
+     * Creates a control, order checking is disabled by default, and the mock
+     * objects created by this control will return <code>0</code>,
+     * <code>null</code> or <code>false</code> for unexpected invocations.
+     * 
+     * @return the control.
+     */
+    public IMocksControl createNiceControl() {
+        final IMocksControl ctrl = EasyMock.createNiceControl();
+        controls.add(ctrl);
+        return ctrl;
+    }
+
+    /**
+     * Switches all registered mock objects (more exactly: the controls of the
+     * mock objects) to replay mode. For details, see the EasyMock
+     * documentation.
+     */
+    public void replayAll() {
+        for (final IMocksControl c : controls) {
+            c.replay();
+        }
+    }
+
+    /**
+     * Resets all registered mock objects (more exactly: the controls of the
+     * mock objects). For details, see the EasyMock documentation.
+     */
+    public void resetAll() {
+        for (final IMocksControl c : controls) {
+            c.reset();
+        }
+    }
+
+    /**
+     * Verifies all registered mock objects (more exactly: the controls of the
+     * mock objects).
+     */
+    public void verifyAll() {
+        for (final IMocksControl c : controls) {
+            c.verify();
+        }
+    }
+
+    /**
+     * Resets all registered mock objects (more exactly: the controls of the
+     * mock objects) and turn them to a mock with nice behavior. For details,
+     * see the EasyMock documentation.
+     */
+    public void resetAllToNice() {
+        for (final IMocksControl c : controls) {
+            c.resetToNice();
+        }
+    }
+
+    /**
+     * Resets all registered mock objects (more exactly: the controls of the
+     * mock objects) and turn them to a mock with default behavior. For details,
+     * see the EasyMock documentation.
+     */
+    public void resetAllToDefault() {
+        for (final IMocksControl c : controls) {
+            c.resetToDefault();
+        }
+    }
+
+    /**
+     * Resets all registered mock objects (more exactly: the controls of the
+     * mock objects) and turn them to a mock with strict behavior. For details,
+     * see the EasyMock documentation.
+     */
+    public void resetAllToStrict() {
+        for (final IMocksControl c : controls) {
+            c.resetToStrict();
+        }
+    }
+
+    /**
+     * Inject a mock to every fields annotated with {@link Mock} on the class passed
+     * in parameter. Then, inject these mocks to the fields of every class annotated with {@link TestSubject}.
+     * <p>
+     * The rules are
+     * <ul>
+     *     <li>Static and final fields are ignored</li>
+     *     <li>If a mock can be assigned to a field, do it. The same mock an be assigned more than once</li>
+     *     <li>If no mock can be assigned to a field, skip it silently</li>
+     *     <li>If two mocks can be assigned to the same field, return an error</li>
+     * </ul>
+     * Fields are searched recursively on the superclasses
+     * <p>
+     * <b>Note:</b> If the parameter extends {@link EasyMockSupport}, the mocks will be created using it to allow
+     * <code>replayAll/verifyAll</code> to work afterwards
+     * @param obj the object on which to inject mocks
+     * @since 3.2
+     */
+    public static void injectMocks(final Object obj) {
+        List<Field> injectMockFields = new ArrayList<Field>(1);
+        List<Object> mocks = new ArrayList<Object>(5);
+
+        Class<?> c = obj.getClass();
+        while(c != Object.class) {
+            createMocksForAnnotations(c, obj, mocks, injectMockFields);
+            c = c.getSuperclass();
+        }
+
+        for(Field f : injectMockFields) {
+            f.setAccessible(true);
+            Object o;
+            try {
+                o = f.get(obj);
+            } catch (IllegalAccessException e) {
+                // ///CLOVER:OFF
+                throw new RuntimeException(e);
+                // ///CLOVER:ON
+            }
+            c = o.getClass();
+            while(c != Object.class) {
+                injectMocksOnClass(c, o, mocks);
+                c = c.getSuperclass();
+            }
+        }
+    }
+
+    /**
+     * Try to inject a mock to every fields in the class
+     *
+     * @param clazz class where the fields are taken
+     * @param obj object being a instance of clazz
+     * @param mocks list of possible mocks
+     */
+    private static void injectMocksOnClass(Class<?> clazz, Object obj, List<Object> mocks) {
+        final Field[] fields = clazz.getDeclaredFields();
+        for (final Field f : fields) {
+            // Skip final or static fields
+            if((f.getModifiers() & (Modifier.STATIC + Modifier.FINAL)) != 0) {
+                continue;
+            }
+            final Class<?> type = f.getType();
+            Object toAssign = null;
+            for(Object mock : mocks) {
+                if(type.isAssignableFrom(mock.getClass())) {
+                    if(toAssign != null) {
+                        throw new RuntimeException("At least two mocks can be assigned to " + f + ": " + toAssign + " and " + mock);
+                    }
+                    toAssign = mock;
+                }
+            }
+            if(toAssign == null) {
+                continue;
+            }
+            f.setAccessible(true);
+            try {
+                f.set(obj, toAssign);
+            } catch (final IllegalAccessException e) {
+                // ///CLOVER:OFF
+                throw new RuntimeException(e);
+                // ///CLOVER:ON
+            }
+        }
+    }
+
+    /**
+     * Create the mocks and find the fields annotated with {@link TestSubject}
+     *
+     * @param clazz class to search
+     * @param obj object of the class
+     * @param mocks output parameter where the created mocks are added
+     * @param injectMockFields output parameter where the fields to inject are added
+     */
+    private static void createMocksForAnnotations(Class<?> clazz, Object obj, List<Object> mocks, List<Field> injectMockFields) {
+        final Field[] fields = clazz.getDeclaredFields();
+        for (final Field f : fields) {
+            final TestSubject ima = f.getAnnotation(TestSubject.class);
+            if(ima != null) {
+                injectMockFields.add(f);
+                continue;
+            }
+            final Mock annotation = f.getAnnotation(Mock.class);
+            if (annotation == null) {
+                continue;
+            }
+            final Class<?> type = f.getType();
+            String name = annotation.name();
+            // Empty string means we are on the default value which we means no name (aka null) from the EasyMock point of view
+            name = (name.length() == 0 ? null : name);
+
+            MockType mockType = annotation.type();
+            Object o;
+            if (obj instanceof EasyMockSupport) {
+                o = ((EasyMockSupport) obj).createMock(name, mockType, type);
+            }
+            else {
+                o = EasyMock.createMock(name, mockType, type);
+            }
+            f.setAccessible(true);
+            try {
+                f.set(obj, o);
+            } catch (final IllegalAccessException e) {
+                // ///CLOVER:OFF
+                throw new RuntimeException(e);
+                // ///CLOVER:ON
+            }
+            mocks.add(o);
+        }
+    }
+}
diff --git a/src/org/easymock/IAnswer.java b/src/org/easymock/IAnswer.java
index c5e7129..1b0dab4 100644
--- a/src/org/easymock/IAnswer.java
+++ b/src/org/easymock/IAnswer.java
@@ -1,23 +1,40 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-/**
- * Used to answer expected calls.
- * @param <T> the type to return.
- */
-public interface IAnswer<T> {
-    /**
-     * is called by EasyMock to answer an expected call. 
-     * The answer may be to return a value, or to throw an exception.
-     * The arguments of the call for which the answer is generated 
-     * are available via {@link EasyMock#getCurrentArguments()} - be careful
-     * here, using the arguments is not refactoring-safe.
-     * 
-     * @return the value to be returned
-     * @throws Throwable the throwable to be thrown
-     */
-    T answer() throws Throwable;
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+/**
+ * Used to answer expected calls.
+ * 
+ * @param <T>
+ *            the type to return.
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public interface IAnswer<T> {
+
+    /**
+     * Is called by EasyMock to answer an expected call. The answer may be to
+     * return a value, or to throw an exception. The arguments of the call for
+     * which the answer is generated are available via
+     * {@link EasyMock#getCurrentArguments()} - be careful here, using the
+     * arguments is not refactoring-safe.
+     * 
+     * @return the value to be returned
+     * @throws Throwable
+     *             the throwable to be thrown
+     */
+    T answer() throws Throwable;
+}
diff --git a/src/org/easymock/IArgumentMatcher.java b/src/org/easymock/IArgumentMatcher.java
index f734194..15cb66c 100644
--- a/src/org/easymock/IArgumentMatcher.java
+++ b/src/org/easymock/IArgumentMatcher.java
@@ -1,36 +1,51 @@
-/*
- * Copyright (c) 2001-2006 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-/**
- * Decides whether an actual argument is accepted.
- */
-public interface IArgumentMatcher {
-    
-    /**
-     * Returns whether this matcher accepts the given argument. 
-     * <p>
-     * Like Object.equals(), it should be aware that the argument passed might 
-     * be null and of any type. So you will usually start the method with an 
-     * instanceof and/or null check.
-     * <p>
-     * The method should <b>never</b> assert if the argument doesn't match. It
-     * should only return false. EasyMock will take care of asserting if the
-     * call is really unexpected.
-     * 
-     * @param argument the argument
-     * @return whether this matcher accepts the given argument.
-     */
-    boolean matches(Object argument);
-
-    /**
-     * Appends a string representation of this matcher to the given buffer. In case
-     * of failure, the printed message will show this string to allow to know which
-     * matcher was used for the failing call.
-     * 
-     * @param buffer the buffer to which the string representation is appended.
-     */
-    void appendTo(StringBuffer buffer);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+/**
+ * Decides whether an actual argument is accepted.
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public interface IArgumentMatcher {
+
+    /**
+     * Returns whether this matcher accepts the given argument.
+     * <p>
+     * Like Object.equals(), it should be aware that the argument passed might
+     * be null and of any type. So you will usually start the method with an
+     * instanceof and/or null check.
+     * <p>
+     * The method should <b>never</b> assert if the argument doesn't match. It
+     * should only return false. EasyMock will take care of asserting if the
+     * call is really unexpected.
+     * 
+     * @param argument
+     *            the argument
+     * @return whether this matcher accepts the given argument.
+     */
+    boolean matches(Object argument);
+
+    /**
+     * Appends a string representation of this matcher to the given buffer. In
+     * case of failure, the printed message will show this string to allow to
+     * know which matcher was used for the failing call.
+     * 
+     * @param buffer
+     *            the buffer to which the string representation is appended.
+     */
+    void appendTo(StringBuffer buffer);
+}
diff --git a/src/org/easymock/IExpectationSetters.java b/src/org/easymock/IExpectationSetters.java
index e6d7e63..f7d9a5c 100644
--- a/src/org/easymock/IExpectationSetters.java
+++ b/src/org/easymock/IExpectationSetters.java
@@ -1,115 +1,154 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-/**
- * Allows setting expectations for an associated expected invocation.
- * Implementations of this interface are returned by
- * {@link EasyMock#expect(Object)}, and by {@link EasyMock#expectLastCall()}.
- */
-public interface IExpectationSetters<T> {
-
-    /**
-     * Sets a return value that will be returned for the expected invocation.
-     * 
-     * @param value
-     *            the value to return.
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> andReturn(T value);
-
-    /**
-     * Sets a throwable that will be thrown for the expected invocation.
-     * 
-     * @param throwable
-     *            the throwable to throw.
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> andThrow(Throwable throwable);
-
-    /**
-     * Sets an object that will be used to calculate the answer for the expected
-     * invocation (either return a value, or throw an exception).
-     * 
-     * @param answer
-     *            the object used to answer the invocation.
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> andAnswer(IAnswer<? extends T> answer);
-
-    /**
-     * Sets a stub return value that will be returned for the expected
-     * invocation.
-     * 
-     * @param value
-     *            the value to return.
-     */
-    void andStubReturn(T value);
-
-    /**
-     * Sets a stub throwable that will be thrown for the expected invocation.
-     * 
-     * @param throwable
-     *            the throwable to throw.
-     */
-    void andStubThrow(Throwable throwable);
-
-    /**
-     * Sets a stub object that will be used to calculate the answer for the
-     * expected invocation (either return a value, or throw an exception).
-     * 
-     * @param answer
-     *            the object used to answer the invocation.
-     */
-    void andStubAnswer(IAnswer<? extends T> answer);
-
-    /**
-     * Sets stub behavior for the expected invocation (this is needed for void
-     * methods).
-     */
-    void asStub();
-
-    /**
-     * Expect the last invocation <code>count</code> times.
-     * 
-     * @param count
-     *            the number of invocations expected.
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> times(int count);
-
-    /**
-     * Expect the last invocation between <code>min</code> and
-     * <code>max</code> times.
-     * 
-     * @param min
-     *            the minimum number of invocations expected.
-     * @param max
-     *            the maximum number of invocations expected.
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> times(int min, int max);
-
-    /**
-     * Expect the last invocation once. This is default in EasyMock.
-     * 
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> once();
-
-    /**
-     * Expect the last invocation at least once.
-     * 
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> atLeastOnce();
-
-    /**
-     * Expect the last invocation any times.
-     * 
-     * @return this object to allow method call chaining.
-     */
-    IExpectationSetters<T> anyTimes();
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+/**
+ * Allows setting expectations for an associated expected invocation.
+ * Implementations of this interface are returned by
+ * {@link EasyMock#expect(Object)}, and by {@link EasyMock#expectLastCall()}.
+ * 
+ * @param <T>
+ *            type of what should be returned by this expected call
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public interface IExpectationSetters<T> {
+
+    /**
+     * Sets a return value that will be returned for the expected invocation.
+     * 
+     * @param value
+     *            the value to return.
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> andReturn(T value);
+
+    /**
+     * Sets a throwable that will be thrown for the expected invocation.
+     * 
+     * @param throwable
+     *            the throwable to throw.
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> andThrow(Throwable throwable);
+
+    /**
+     * Sets an object that will be used to calculate the answer for the expected
+     * invocation (either return a value, or throw an exception).
+     * 
+     * @param answer
+     *            the object used to answer the invocation.
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> andAnswer(IAnswer<? extends T> answer);
+
+    /**
+     * Sets an object implementing the same interface as the mock. The expected
+     * method call will be delegated to it with the actual arguments. The answer
+     * returned by this call will then be the answer returned by the mock
+     * (either return a value, or throw an exception).
+     * 
+     * @param delegateTo
+     *            the object the call is delegated to.
+     * @return the value returned by the delegated call.
+     */
+    IExpectationSetters<T> andDelegateTo(Object delegateTo);
+
+    /**
+     * Sets a stub return value that will be returned for the expected
+     * invocation.
+     * 
+     * @param value
+     *            the value to return.
+     */
+    void andStubReturn(T value);
+
+    /**
+     * Sets a stub throwable that will be thrown for the expected invocation.
+     * 
+     * @param throwable
+     *            the throwable to throw.
+     */
+    void andStubThrow(Throwable throwable);
+
+    /**
+     * Sets a stub object that will be used to calculate the answer for the
+     * expected invocation (either return a value, or throw an exception).
+     * 
+     * @param answer
+     *            the object used to answer the invocation.
+     */
+    void andStubAnswer(IAnswer<? extends T> answer);
+
+    /**
+     * Sets a stub object implementing the same interface as the mock. The
+     * expected method call will be delegated to it with the actual arguments.
+     * The answer returned by this call will then be the answer returned by the
+     * mock (either return a value, or throw an exception).
+     * 
+     * @param delegateTo
+     *            the object the call is delegated to.
+     */
+    void andStubDelegateTo(Object delegateTo);
+
+    /**
+     * Sets stub behavior for the expected invocation (this is needed for void
+     * methods).
+     */
+    void asStub();
+
+    /**
+     * Expect the last invocation <code>count</code> times.
+     * 
+     * @param count
+     *            the number of invocations expected.
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> times(int count);
+
+    /**
+     * Expect the last invocation between <code>min</code> and <code>max</code>
+     * times.
+     * 
+     * @param min
+     *            the minimum number of invocations expected.
+     * @param max
+     *            the maximum number of invocations expected.
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> times(int min, int max);
+
+    /**
+     * Expect the last invocation once. This is default in EasyMock.
+     * 
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> once();
+
+    /**
+     * Expect the last invocation at least once.
+     * 
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> atLeastOnce();
+
+    /**
+     * Expect the last invocation any times.
+     * 
+     * @return this object to allow method call chaining.
+     */
+    IExpectationSetters<T> anyTimes();
+}
diff --git a/src/org/easymock/IMockBuilder.java b/src/org/easymock/IMockBuilder.java
new file mode 100644
index 0000000..8088f24
--- /dev/null
+++ b/src/org/easymock/IMockBuilder.java
@@ -0,0 +1,336 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Helps the creation of partial mocks with {@link EasyMock}.
+ * 
+ * <p>
+ * Example of usage:
+ * 
+ * <pre>
+ * public class MyClass {
+ *     public MyClass(A a, B b) {
+ *     }
+ * }
+ * 
+ * public class MyClassTest {
+ *     @Test
+ *     public void testFoo() throws Exception {
+ *         IMocksControl mockControl = createControl();
+ *         A a = mockControl.createMock(A.class);
+ *         B b = mockControl.createMock(B.class);
+ * 
+ *         MyClass myClass = createMockBuilder(MyClass.class)
+ *                 .withConstructor(a, b).createMock(mockControl);
+ * 
+ *         // Set the expectations of A and B and test some method in MyClass
+ *     }
+ * }
+ * </pre>
+ * 
+ * <p>
+ * This class also has support for partial mocks as shown by the example below:
+ * 
+ * <pre>
+ * public class MyMockedClass {
+ *     // Empty class is also valid for {@link IMockBuilder}.
+ *     public MyMockedClass() {
+ *     }
+ * 
+ *     public void foo(int a) {
+ *         blah(a);
+ *         bleh();
+ *     }
+ * 
+ *     public void blah(int a) {
+ *     }
+ * 
+ *     public void bleh() {
+ *     }
+ * }
+ * 
+ * public class MyMockedClassTest {
+ *     @Test
+ *     public void testFoo() throws Exception {
+ *         MyMockedClass myMockedClass = createMockBuilder(MyMockedClass.class)
+ *                 .withConstructor().addMockedMethod("blah", int.class)
+ *                 .addMockedMethod("bleh").createMock();
+ * 
+ *         // These are the expectations.
+ *         myMockedClass.blah(1);
+ *         myMockedClass.bleh();
+ *         replay(myMockedClass);
+ * 
+ *         myMockedClass.foo(1);
+ *         verify(myMockedClass);
+ *     }
+ * }
+ * </pre>
+ * 
+ * <p>
+ * Warning: There may be ambiguities when there are two different constructors
+ * with compatible types. For instance:
+ * 
+ * <pre>
+ * public class A {
+ * }
+ * 
+ * public class B extends A {
+ * }
+ * 
+ * public class ClassWithAmbiguity {
+ *     public ClassWithAmbiguity(A a) {
+ *     }
+ * 
+ *     public ClassWithAmbiguity(B b) {
+ *     }
+ * }
+ * </pre>
+ * 
+ * will cause problems if using {@link #withConstructor(Object...)}. To solve
+ * this, you can explicitly define the constructor parameter types to use by
+ * calling {@link #withConstructor(Class...)} and then
+ * {@link #withArgs(Object...)}, like this:
+ * 
+ * <pre>
+ * createMockBuilder(MyMockedClass.class).withConstructor(A.class).withArgs(
+ *         new A()).createMock();
+ * </pre>
+ * 
+ * @param <T>
+ *            type of the object being created
+ * 
+ * @author Henri Tremblay
+ */
+public interface IMockBuilder<T> {
+
+    /**
+     * Adds a method to be mocked in the testing class. Each call will add a new
+     * method to the result mock.
+     * 
+     * The method is searched for in the class itself as well as superclasses.
+     * 
+     * @param method
+     *            method to be mocked
+     * @return this
+     */
+    IMockBuilder<T> addMockedMethod(Method method);
+
+    /**
+     * Adds a method to be mocked in the testing class. Each call will add a new
+     * method to the result mock.
+     * 
+     * The method is searched for in the class itself as well as superclasses.
+     * 
+     * There must be no overload of the method. You will have to rely on the
+     * other <code>addMockedMethod</code>s in this class if that is the case.
+     * 
+     * @param methodName
+     *            name of the method to be mocked
+     * @return this
+     */
+    IMockBuilder<T> addMockedMethod(String methodName);
+
+    /**
+     * Adds a method to be mocked in the testing class. Each call will add a new
+     * method to the result mock.
+     * 
+     * The method is searched for in the class itself as well as superclasses.
+     * 
+     * @param methodName
+     *            name of the method to be mocked
+     * @param parameterTypes
+     *            types of the parameters of the method
+     * @return this
+     */
+    IMockBuilder<T> addMockedMethod(String methodName, Class<?>... parameterTypes);
+
+    /**
+     * Adds methods to be mocked in the testing class. Same as
+     * {@link #addMockedMethod(String)} but to mock many methods at once.
+     * 
+     * @param methodNames
+     *            names of the methods to be mocked
+     * @return this
+     */
+    IMockBuilder<T> addMockedMethods(String... methodNames);
+
+    /**
+     * Adds methods to be mocked in the testing class. Same as
+     * {@link #addMockedMethod(Method)} but to mock many methods at once.
+     * 
+     * @param methods
+     *            methods to be mocked
+     * @return this
+     */
+    IMockBuilder<T> addMockedMethods(Method... methods);
+
+    /**
+     * Defines the constructor to use to instantiate the mock. It is expected
+     * that you call {@link #withArgs} with the actual constructor argument
+     * values after this.
+     * 
+     * @param constructor
+     *            the constructor to be called
+     * @return this
+     */
+    IMockBuilder<T> withConstructor(Constructor<?> constructor);
+
+    /**
+     * Defines the empty constructor should be called.
+     * 
+     * @return this
+     */
+    IMockBuilder<T> withConstructor();
+
+    /**
+     * Defines the constructor parameters for the mocked class. The builder will
+     * automatically find a constructor with compatible argument types. This
+     * throws an exception if there is more than one constructor which would
+     * accept the given parameters.
+     * 
+     * @param initArgs
+     *            arguments of the constructor
+     * @return this
+     */
+    IMockBuilder<T> withConstructor(Object... initArgs);
+
+    /**
+     * Defines the exact argument types for the constructor to use. It is
+     * expected that you call {@link #withArgs} with the actual constructor
+     * argument values after this.
+     * 
+     * @param argTypes
+     *            the exact argument types of the constructor
+     * @return this
+     */
+    IMockBuilder<T> withConstructor(Class<?>... argTypes);
+
+    /**
+     * Defines the arguments to be passed to the constructor of the class. The
+     * types of the arguments must match those previously defined with
+     * {@link #withConstructor(Class...)} or
+     * {@link #withConstructor(Constructor)}.
+     * 
+     * @param initArgs
+     *            the arguments to pass to the constructor
+     * @return this
+     */
+    IMockBuilder<T> withArgs(Object... initArgs);
+
+    /**
+     * Create mock of the request type from this builder. The same builder can be called to
+     * create multiple mocks.
+     * 
+     * @param type the mock type
+     * @return the newly created mock
+     * @since 3.2
+     */
+    T createMock(MockType type);
+
+    /**
+     * Create a strict mock from this builder. The same builder can be called to
+     * create multiple mocks.
+     * 
+     * @return the newly created mock
+     */
+    T createStrictMock();
+
+    /**
+     * Create a default mock from this builder. The same builder can be called
+     * to create multiple mocks.
+     * 
+     * @return the newly created mock
+     */
+    T createMock();
+
+    /**
+     * Create a nice mock from this builder. The same builder can be called to
+     * create multiple mocks.
+     * 
+     * @return the newly created mock
+     */
+    T createNiceMock();
+
+    /**
+     * Create mock from the provided mock control using the arguments passed to
+     * the builder.
+     * 
+     * @param control
+     *            {@link org.easymock.IMocksControl} used to create the object
+     * @return the newly created mock
+     */
+    T createMock(IMocksControl control);
+
+    /**
+     * Create a named mock of the request type from this builder. The same builder can be 
+     * called to create multiple mocks.
+     * 
+     * @param name
+     *            the mock name
+     * @param type
+     *            the mock type
+     * @return the newly created mock
+     * @since 3.2
+     */
+    T createMock(String name, MockType type);
+
+    /**
+     * Create a named strict mock from this builder. The same builder can be
+     * called to create multiple mocks.
+     * 
+     * @param name
+     *            the mock name
+     * @return the newly created mock
+     */
+    T createStrictMock(String name);
+
+    /**
+     * Create named mock from the provided mock control using the arguments
+     * passed to the builder.
+     * 
+     * @param name
+     *            the mock name
+     * @return the newly created mock
+     */
+    T createMock(String name);
+
+    /**
+     * Create a named nice mock from this builder. The same builder can be
+     * called to create multiple mocks.
+     * 
+     * @param name
+     *            the mock name
+     * @return the newly created mock
+     */
+    T createNiceMock(String name);
+
+    /**
+     * Create named mock from the provided mock control using the arguments
+     * passed to the builder.
+     * 
+     * @param name
+     *            the mock name
+     * @param control
+     *            {@link org.easymock.IMocksControl} used to create the object
+     * @return the newly created mock
+     */
+    T createMock(String name, IMocksControl control);
+}
diff --git a/src/org/easymock/IMocksControl.java b/src/org/easymock/IMocksControl.java
index 17f9ff6..b397645 100644
--- a/src/org/easymock/IMocksControl.java
+++ b/src/org/easymock/IMocksControl.java
@@ -1,75 +1,191 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-/**
- * Controls all the mock objects created by it.
- * For details, see the EasyMock documentation.
- */
-public interface IMocksControl {
-    /**
-     * Creates a mock object that implements the given interface.
-     * @param <T> the interface that the mock object should implement.
-     * @param toMock the class of the interface that the mock object should implement.
-     * @return the mock object.
-     */
-    <T> T createMock(Class<T> toMock);
-
-    /**
-     * Creates a mock object that implements the given interface.
-     * @param name the name of the mock object .
-     * @param toMock the class of the interface that the mock object should implement.
-     * @param <T> the interface that the mock object should implement.
-     * @return the mock object.
-     * @throws IllegalArgumentException if the name is not a valid Java identifier.
-     */
-    <T> T createMock(String name, Class<T> toMock);
-
-    /**
-     * Removes all expectations for the mock objects of this control.
-     */
-    void reset();
-    
-    /**
-     * Removes all expectations for the mock objects of this control and turn
-     * them to nice mocks.
-     */
-    void resetToNice();
-    
-    /**
-     * Removes all expectations for the mock objects of this control and turn
-     * them to default mocks.
-     */
-    void resetToDefault();
-    
-    /**
-     * Removes all expectations for the mock objects of this control and turn
-     * them to strict mocks.
-     */
-    void resetToStrict();
-
-    /**
-     * Switches the control from record mode to replay mode.
-     */
-    void replay();
-
-    /**
-     * Verifies that all expectations were met. 
-     */
-    void verify();
-
-    /**
-     * Switches order checking on and off.
-     * @param state <code>true</code> switches order checking on, <code>false</code> switches it off.
-     */
-    void checkOrder(boolean state);
-    
-    /**
-     * Makes the mock thread safe.
-     * 
-     * @param threadSafe If the mock should be thread safe or not
-     */
-    void makeThreadSafe(boolean threadSafe);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.reflect.Method;
+
+/**
+ * Controls all the mock objects created by it. For details, see the EasyMock
+ * documentation.
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public interface IMocksControl {
+
+    /**
+     * Creates a mock object that implements the given interface.
+     * 
+     * @param <T>
+     *            the interface or class that the mock object should
+     *            implement/extend.
+     * @param toMock
+     *            the interface or class that the mock object should
+     *            implement/extend.
+     * @return the mock object.
+     */
+    <T> T createMock(Class<T> toMock);
+
+    /**
+     * Creates a mock object that implements the given interface.
+     * 
+     * @param <T>
+     *            the interface or class that the mock object should
+     *            implement/extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the interface or class that the mock object should
+     *            implement/extend.
+     * @return the mock object.
+     * @throws IllegalArgumentException
+     *             if the name is not a valid Java identifier.
+     */
+    <T> T createMock(String name, Class<T> toMock);
+
+    /**
+     * Creates a mock object that implements the given class.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link EasyMock#createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    <T> T createMock(Class<T> toMock, Method... mockedMethods);
+
+    /**
+     * Creates a mock object that implements the given class.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link EasyMock#createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    <T> T createMock(Class<T> toMock, ConstructorArgs constructorArgs, Method... mockedMethods);
+
+    /**
+     * Creates a mock object that implements the given class.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link EasyMock#createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    <T> T createMock(String name, Class<T> toMock, Method... mockedMethods);
+
+    /**
+     * Creates a mock object that implements the given class.
+     * 
+     * @param <T>
+     *            the class that the mock object should extend.
+     * @param name
+     *            the name of the mock object.
+     * @param toMock
+     *            the class that the mock object should extend.
+     * @param constructorArgs
+     *            constructor and parameters used to instantiate the mock.
+     * @param mockedMethods
+     *            methods that will be mocked, other methods will behave
+     *            normally
+     * @return the mock object.
+     * 
+     * @deprecated Use {@link EasyMock#createMockBuilder(Class)} instead
+     */
+    @Deprecated
+    <T> T createMock(String name, Class<T> toMock, ConstructorArgs constructorArgs, Method... mockedMethods);
+
+    /**
+     * Removes all expectations for the mock objects of this control.
+     */
+    void reset();
+
+    /**
+     * Removes all expectations for the mock objects of this control and turn
+     * them to nice mocks.
+     */
+    void resetToNice();
+
+    /**
+     * Removes all expectations for the mock objects of this control and turn
+     * them to default mocks.
+     */
+    void resetToDefault();
+
+    /**
+     * Removes all expectations for the mock objects of this control and turn
+     * them to strict mocks.
+     */
+    void resetToStrict();
+
+    /**
+     * Switches the control from record mode to replay mode.
+     */
+    void replay();
+
+    /**
+     * Verifies that all expectations were met.
+     */
+    void verify();
+
+    /**
+     * Switches order checking on and off.
+     * 
+     * @param state
+     *            <code>true</code> switches order checking on,
+     *            <code>false</code> switches it off.
+     */
+    void checkOrder(boolean state);
+
+    /**
+     * Makes the mock thread safe.
+     * 
+     * @param threadSafe
+     *            If the mock should be thread safe or not
+     */
+    void makeThreadSafe(boolean threadSafe);
+
+    /**
+     * Check that the mock is called from only one thread
+     * 
+     * @param shouldBeUsedInOneThread
+     *            If it should be used in one thread only or not
+     */
+    void checkIsUsedInOneThread(boolean shouldBeUsedInOneThread);
+}
diff --git a/src/org/easymock/LogicalOperator.java b/src/org/easymock/LogicalOperator.java
index 859598e..cbf19c7 100644
--- a/src/org/easymock/LogicalOperator.java
+++ b/src/org/easymock/LogicalOperator.java
@@ -1,48 +1,66 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Henri Tremblay.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-/**
- * See {@link EasyMock#cmp}
- */
-public enum LogicalOperator {
-    LESS_THAN("<") {
-        public boolean matchResult(int result) {
-            return result < 0;
-        }
-    },
-    LESS_OR_EQUAL("<=") {
-        public boolean matchResult(int result) {
-            return result <= 0;
-        }
-    },
-    EQUAL("==") {
-        public boolean matchResult(int result) {
-            return result == 0;
-        }
-    },
-    GREATER_OR_EQUAL(">=") {
-        public boolean matchResult(int result) {
-            return result >= 0;
-        }
-    },
-    GREATER(">") {
-        public boolean matchResult(int result) {
-            return result > 0;
-        }
-    };
-    
-    private String symbol;
-    
-    private LogicalOperator(String symbol) {
-        this.symbol = symbol;
-    }
-    
-    public String getSymbol() {
-        return symbol;
-    }
-    
-    public abstract boolean matchResult(int result);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+/**
+ * See {@link EasyMock#cmp}
+ * 
+ * @author Henri Tremblay
+ */
+public enum LogicalOperator {
+    LESS_THAN("<") {
+        @Override
+        public boolean matchResult(final int result) {
+            return result < 0;
+        }
+    },
+    LESS_OR_EQUAL("<=") {
+        @Override
+        public boolean matchResult(final int result) {
+            return result <= 0;
+        }
+    },
+    EQUAL("==") {
+        @Override
+        public boolean matchResult(final int result) {
+            return result == 0;
+        }
+    },
+    GREATER_OR_EQUAL(">=") {
+        @Override
+        public boolean matchResult(final int result) {
+            return result >= 0;
+        }
+    },
+    GREATER(">") {
+        @Override
+        public boolean matchResult(final int result) {
+            return result > 0;
+        }
+    };
+
+    private String symbol;
+
+    private LogicalOperator(final String symbol) {
+        this.symbol = symbol;
+    }
+
+    public String getSymbol() {
+        return symbol;
+    }
+
+    public abstract boolean matchResult(int result);
+}
diff --git a/src/org/easymock/Mock.java b/src/org/easymock/Mock.java
new file mode 100644
index 0000000..5149ebd
--- /dev/null
+++ b/src/org/easymock/Mock.java
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation to set on a field so that {@link EasyMockRunner} or {@link EasyMockSupport#injectMocks(Object)}
+ * will inject a mock to it.
+ * <p>
+ * Doing<br>
+ * <code>@Mock private MyClass mock;</code><br> 
+ * is strictly identical to doing<br>
+ * <code>private MyClass mock = createMock(MyClass.class);</code>
+ * 
+ * @author Henri Tremblay
+ * @since 3.2
+ */
+ at Target({ ElementType.FIELD, ElementType.ANNOTATION_TYPE })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+public @interface Mock {
+
+    /** Type of mock to create */
+    MockType type() default MockType.DEFAULT;
+
+    /** Name of the mock to be created */
+    String name() default "";
+}
diff --git a/src/org/easymock/MockControl.java b/src/org/easymock/MockControl.java
deleted file mode 100644
index 9f04fb9..0000000
--- a/src/org/easymock/MockControl.java
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock;
-
-import static org.easymock.EasyMock.expect;
-
-import org.easymock.internal.*;
-
-/**
- * A <code>MockControl</code> object controls the behavior of its associated
- * mock object. For more information, see the EasyMock documentation.
- * 
- * @deprecated Since EasyMock 2.0, static methods on <code>EasyMock</code> are
- * used to create and control mock objects.
- */
-public class MockControl<T> {
-    private final T mock;
-
-    private final MocksControl ctrl;
-
-    protected MockControl(MocksControl ctrl, Class<T> toMock) {
-        this.ctrl = ctrl;
-        this.mock = ctrl.createMock(toMock);
-    }
-
-    /**
-     * Creates a mock control object for the specified interface. The
-     * <code>MockControl</code> and its associated mock object will not check
-     * the order of expected method calls. An unexpected method call on the mock
-     * object will lead to an <code>AssertionError</code>.
-     * 
-     * @param toMock
-     *            the class of the interface to mock.
-     * @return the mock control.
-     */
-    public static <T> MockControl<T> createControl(Class<T> toMock) {
-        return new MockControl<T>((MocksControl) EasyMock.createControl(),
-                toMock);
-    }
-
-    /**
-     * Creates a mock control object for the specified interface. The
-     * <code>MockControl</code> and its associated mock object will check the
-     * order of expected method calls. An unexpected method call on the mock
-     * object will lead to an <code>AssertionError</code>.
-     * 
-     * @param toMock
-     *            the class of the interface to mock.
-     * @return the mock control.
-     */
-    public static <T extends Object> MockControl<T> createStrictControl(Class<T> toMock) {
-        return new MockControl<T>(
-                (MocksControl) EasyMock.createStrictControl(), toMock);
-    }
-
-    /**
-     * Creates a mock control object for the specified interface. The
-     * <code>MockControl</code> and its associated mock object will not check
-     * the order of expected method calls. An unexpected method call on the mock
-     * object will return an empty value (0, null, false).
-     * 
-     * @param toMock
-     *            the class of the interface to mock.
-     * @return the mock control.
-     */
-    public static <T> MockControl<T> createNiceControl(Class<T> toMock) {
-        return new MockControl<T>((MocksControl) EasyMock.createNiceControl(),
-                toMock);
-    }
-
-    /**
-     * Returns the mock object.
-     * 
-     * @return the mock object of this control
-     */
-    public T getMock() {
-        return mock;
-    }
-
-    /**
-     * Resets the mock control and the mock object to the state directly after
-     * creation.
-     */
-    public final void reset() {
-        ctrl.reset();
-    }
-
-    /**
-     * Switches the mock object from record state to replay state. For more
-     * information, see the EasyMock documentation.
-     * 
-     * @throws IllegalStateException
-     *             if the mock object already is in replay state.
-     */
-    public void replay() {
-        ctrl.replay();
-    }
-
-    /**
-     * Verifies that all expectations have been met. For more information, see
-     * the EasyMock documentation.
-     * 
-     * @throws IllegalStateException
-     *             if the mock object is in record state.
-     * @throws AssertionError
-     *             if any expectation has not been met.
-     */
-    public void verify() {
-        ctrl.verify();
-    }
-
-    /**
-     * Records that the mock object will expect the last method call once, and
-     * will react by returning silently.
-     * 
-     * @exception IllegalStateException
-     *                if the mock object is in replay state, if no method was
-     *                called on the mock object before, or if the last method
-     *                called on the mock was no void method.
-     */
-    public void setVoidCallable() {
-        expectLastCall(
-                "method call on the mock needed before setting void callable")
-                .once();
-    }
-
-    /**
-     * Records that the mock object will expect the last method call once, and
-     * will react by throwing the provided Throwable.
-     * 
-     * @param throwable
-     *            the Throwable to throw.
-     * @exception IllegalStateException
-     *                if the mock object is in replay state or if no method was
-     *                called on the mock object before.
-     * @exception IllegalArgumentException
-     *                if the last method called on the mock cannot throw the
-     *                provided Throwable.
-     * @exception NullPointerException
-     *                if throwable is null.
-     */
-    public void setThrowable(Throwable throwable) {
-        expectLastCall(
-                "method call on the mock needed before setting Throwable")
-                .andThrow(throwable).once();
-    }
-
-    /**
-     * Records that the mock object will expect the last method call once, and
-     * will react by returning the provided return value.
-     * 
-     * @param value
-     *            the return value.
-     * @throws IllegalStateException
-     *             if the mock object is in replay state, if no method was
-     *             called on the mock object before. or if the last method
-     *             called on the mock does not return <code>boolean</code>.
-     */
-    public void setReturnValue(Object value) {
-        expectLastCall(
-                "method call on the mock needed before setting return value")
-                .andReturn(value).once();
-    }
-
-    /**
-     * Records that the mock object will expect the last method call a fixed
-     * number of times, and will react by returning silently.
-     * 
-     * @param times
-     *            the number of times that the call is expected.
-     * @exception IllegalStateException
-     *                if the mock object is in replay state, if no method was
-     *                called on the mock object before, or if the last method
-     *                called on the mock was no void method.
-     */
-    public void setVoidCallable(int times) {
-        expectLastCall(
-                "method call on the mock needed before setting void callable")
-                .times(times);
-    }
-
-    /**
-     * Records that the mock object will expect the last method call a fixed
-     * number of times, and will react by throwing the provided Throwable.
-     * 
-     * @param throwable
-     *            the Throwable to throw.
-     * @param times
-     *            the number of times that the call is expected.
-     * @exception IllegalStateException
-     *                if the mock object is in replay state or if no method was
-     *                called on the mock object before.
-     * @exception IllegalArgumentException
-     *                if the last method called on the mock cannot throw the
-     *                provided Throwable.
-     * @exception NullPointerException
-     *                if throwable is null.
-     */
-    public void setThrowable(Throwable throwable, int times) {
-        expectLastCall(
-                "method call on the mock needed before setting Throwable")
-                .andThrow(throwable).times(times);
-    }
-
-    /**
-     * Records that the mock object will expect the last method call a fixed
-     * number of times, and will react by returning the provided return value.
-     * 
-     * @param value
-     *            the return value.
-     * @param times
-     *            the number of times that the call is expected.
-     * @throws IllegalStateException
-     *             if the mock object is in replay state, if no method was
-     *             called on the mock object before. or if the last method
-     *             called on the mock does not return <code>boolean</code>.
-     */
-    public void setReturnValue(Object value, int times) {
-        expectLastCall(
-                "method call on the mock needed before setting return value")
-                .andReturn(value).times(times);
-    }
-
-    /**
-     * Records that the mock object will expect the last method call a fixed
-     * number of times, and will react by returning the provided return value.
-     * 
-     * @param value
-     *            the return value.
-     * @param range
-     *            the number of times that the call is expected.
-     * @throws IllegalStateException
-     *             if the mock object is in replay state, if no method was
-     *             called on the mock object before. or if the last method
-     *             called on the mock does not return <code>boolean</code>.
-     */
-    public void setReturnValue(Object value, Range range) {
-        IExpectationSetters<Object> setter = expectLastCall(
-                "method call on the mock needed before setting return value")
-                .andReturn(value);
-        callWithConvertedRange(setter, range);
-    }
-
-    /**
-     * Records that the mock object will by default allow the last method
-     * specified by a method call.
-     * 
-     * @exception IllegalStateException
-     *                if the mock object is in replay state, if no method was
-     *                called on the mock object before, or if the last method
-     *                called on the mock was no void method.
-     */
-    public void setDefaultVoidCallable() {
-        ((MocksControl) expectLastCall("method call on the mock needed before setting default void callable"))
-                .setLegacyDefaultVoidCallable();
-    }
-
-    /**
-     * Records that the mock object will by default allow the last method
-     * specified by a method call, and will react by throwing the provided
-     * Throwable.
-     * 
-     * @param throwable
-     *            throwable the throwable to be thrown
-     * @exception IllegalArgumentException
-     *                if the last method called on the mock cannot throw the
-     *                provided Throwable.
-     * @exception NullPointerException
-     *                if throwable is null.
-     * @exception IllegalStateException
-     *                if the mock object is in replay state, or if no method was
-     *                called on the mock object before.
-     */
-    public void setDefaultThrowable(Throwable throwable) {
-        ctrl.setLegacyDefaultThrowable(throwable);
-    }
-
-    /**
-     * Records that the mock object will by default allow the last method
-     * specified by a method call, and will react by returning the provided
-     * return value.
-     * 
-     * @param value
-     *            the return value.
-     * @throws IllegalStateException
-     *             if the mock object is in replay state, if no method was
-     *             called on the mock object before. or if the last method
-     *             called on the mock does not return <code>boolean</code>.
-     */
-    public void setDefaultReturnValue(Object value) {
-        ctrl.setLegacyDefaultReturnValue(value);
-    }
-
-    /**
-     * Sets the ArgumentsMatcher for the last method called on the mock object.
-     * The matcher must be set before any behavior for the method is defined.
-     * 
-     * @throws IllegalStateException
-     *             if called in replay state, or if no method was called on the
-     *             mock object before.
-     */
-    public void setMatcher(ArgumentsMatcher matcher) {
-        ctrl.setLegacyMatcher(matcher);
-    }
-
-    /**
-     * Records that the mock object will expect the last method call between
-     * <code>minCount</code> and <code>maxCount</code> times, and will react
-     * by returning silently.
-     * 
-     * @param minCount
-     *            the minimum number of times that the call is expected.
-     * @param maxCount
-     *            the maximum number of times that the call is expected.
-     * @exception IllegalStateException
-     *                if the mock object is in replay state, if no method was
-     *                called on the mock object before, or if the last method
-     *                called on the mock was no void method.
-     */
-    public void setVoidCallable(int minCount, int maxCount) {
-        expectLastCall(
-                "method call on the mock needed before setting void callable")
-                .times(minCount, maxCount);
-    }
-
-    public void setVoidCallable(Range range) {
-        IExpectationSetters<Object> setter = expectLastCall("method call on the mock needed before setting void callable");
-        callWithConvertedRange(setter, range);
-    }
-
-    /**
-     * Records that the mock object will expect the last method call between
-     * <code>minCount</code> and <code>maxCount</code> times, and will react
-     * by throwing the provided Throwable.
-     * 
-     * @param throwable
-     *            the Throwable to throw.
-     * @param minCount
-     *            the minimum number of times that the call is expected.
-     * @param maxCount
-     *            the maximum number of times that the call is expected.
-     * @exception IllegalStateException
-     *                if the mock object is in replay state or if no method was
-     *                called on the mock object before.
-     * @exception IllegalArgumentException
-     *                if the last method called on the mock cannot throw the
-     *                provided Throwable.
-     * @exception NullPointerException
-     *                if throwable is null.
-     */
-    public void setThrowable(Throwable throwable, int minCount, int maxCount) {
-        expectLastCall(
-                "method call on the mock needed before setting Throwable")
-                .andThrow(throwable).times(minCount, maxCount);
-    }
-
-    public void setThrowable(Throwable throwable, Range range) {
-        IExpectationSetters<Object> setter = expectLastCall(
-                "method call on the mock needed before setting Throwable")
-                .andThrow(throwable);
-        callWithConvertedRange(setter, range);
-    }
-
-    /**
-     * Records that the mock object will expect the last method call between
-     * <code>minCount</code> and <code>maxCount</code> times, and will react
-     * by returning the provided return value.
-     * 
-     * @param value
-     *            the return value.
-     * @param minCount
-     *            the minimum number of times that the call is expected.
-     * @param maxCount
-     *            the maximum number of times that the call is expected.
-     * @throws IllegalStateException
-     *             if the mock object is in replay state, if no method was
-     *             called on the mock object before. or if the last method
-     *             called on the mock does not return <code>boolean</code>.
-     */
-    public void setReturnValue(Object value, int minCount, int maxCount) {
-        expectLastCall(
-                "method call on the mock needed before setting return value")
-                .andReturn(value).times(minCount, maxCount);
-    }
-
-    /**
-     * Exactly one call.
-     */
-    public static final Range ONE = MocksControl.ONCE;
-
-    /**
-     * One or more calls.
-     */
-    public static final Range ONE_OR_MORE = MocksControl.AT_LEAST_ONCE;
-
-    /**
-     * Zero or more calls.
-     */
-    public static final Range ZERO_OR_MORE = MocksControl.ZERO_OR_MORE;
-
-    /**
-     * Matches if each expected argument is equal to the corresponding actual
-     * argument.
-     */
-    public static final ArgumentsMatcher EQUALS_MATCHER = new EqualsMatcher();
-
-    /**
-     * Matches always.
-     */
-    public static final ArgumentsMatcher ALWAYS_MATCHER = new AlwaysMatcher();
-
-    /**
-     * Matches if each expected argument is equal to the corresponding actual
-     * argument for non-array arguments; array arguments are compared with the
-     * appropriate <code>java.util.Arrays.equals()</code> -method.
-     */
-    public static final ArgumentsMatcher ARRAY_MATCHER = new ArrayMatcher();
-
-    /**
-     * Sets the default ArgumentsMatcher for all methods of the mock object. The
-     * matcher must be set before any behavior is defined on the mock object.
-     * 
-     * @throws IllegalStateException
-     *             if called in replay state, or if any behavior is already
-     *             defined on the mock object.
-     */
-    public void setDefaultMatcher(ArgumentsMatcher matcher) {
-        ctrl.setLegacyDefaultMatcher(matcher);
-    }
-
-    /**
-     * Same as {@link MockControl#setReturnValue(Object)}. For explanation, see
-     * "Convenience Methods for Return Values" in the EasyMock documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public <V1, V2 extends V1> void expectAndReturn(V1 ignored, V2 value) {
-        EasyMock.expectLastCall().andReturn(value).once();
-    }
-
-    public void expectAndReturn(int ignored, int value) {
-        this.expectAndReturn((Object) ignored, (Object) value);
-    }
-
-    /**
-     * Same as {@link MockControl#setReturnValue(Object, Range)}. For
-     * explanation, see "Convenience Methods for Return Values" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public <V1, V2 extends V1> void expectAndReturn(V1 ignored, V2 value,
-            Range range) {
-        IExpectationSetters<Object> expectAndReturn = EasyMock.expectLastCall()
-                .andReturn(value);
-        callWithConvertedRange(expectAndReturn, range);
-    }
-
-    public void expectAndReturn(int ignored, int value, Range range) {
-        this.expectAndReturn((Object) ignored, (Object) value, range);
-    }
-
-    /**
-     * Same as {@link MockControl#setReturnValue(Object, int)}. For
-     * explanation, see "Convenience Methods for Return Values" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public <V1, V2 extends V1> void expectAndReturn(V1 ignored, V2 value,
-            int count) {
-        EasyMock.expectLastCall().andReturn(value).times(count);
-    }
-
-    public void expectAndReturn(int ignored, int value, int count) {
-        this.expectAndReturn((Object) ignored, (Object) value, count);
-    }
-
-    /**
-     * Same as {@link MockControl#setReturnValue(Object, int, int)}. For
-     * explanation, see "Convenience Methods for Return Values" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public <V1, V2 extends V1> void expectAndReturn(V1 ignored, V2 value,
-            int min, int max) {
-        EasyMock.expectLastCall().andReturn(value).times(min, max);
-    }
-
-    public void expectAndReturn(int ignored, int value, int min, int max) {
-        this.expectAndReturn((Object) ignored, (Object) value, min, max);
-    }
-
-    /**
-     * Same as {@link MockControl#setThrowable(Throwable)}. For explanation,
-     * see "Convenience Methods for Throwables" in the EasyMock documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public void expectAndThrow(Object ignored, Throwable throwable) {
-        EasyMock.expect(ignored).andThrow(throwable).once();
-    }
-
-    /**
-     * Same as {@link MockControl#setThrowable(Throwable, Range)}. For
-     * explanation, see "Convenience Methods for Throwables" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public void expectAndThrow(Object ignored, Throwable throwable, Range range) {
-        IExpectationSetters<Object> setter = EasyMock.expect(ignored).andThrow(
-                throwable);
-        callWithConvertedRange(setter, range);
-    }
-
-    /**
-     * Same as {@link MockControl#setThrowable(Throwable, int)}. For
-     * explanation, see "Convenience Methods for Throwables" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public void expectAndThrow(Object ignored, Throwable throwable, int count) {
-        expect(ignored).andThrow(throwable).times(count);
-    }
-
-    /**
-     * Same as {@link MockControl#setThrowable(Throwable, int, int)}. For
-     * explanation, see "Convenience Methods for Throwables" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public void expectAndThrow(Object ignored, Throwable throwable, int min,
-            int max) {
-        expect(ignored).andThrow(throwable).times(min, max);
-    }
-
-    /**
-     * Same as {@link MockControl#setDefaultReturnValue(Object)}. For
-     * explanation, see "Convenience Methods for Return Values" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public <V1, V2 extends V1> void expectAndDefaultReturn(V1 ignored, V2 value) {
-        EasyMock.expectLastCall().andStubReturn(value);
-    }
-
-    /**
-     * Same as {@link MockControl#setDefaultThrowable(Throwable)}. For
-     * explanation, see "Convenience Methods for Throwables" in the EasyMock
-     * documentation.
-     * 
-     * @param ignored
-     *            an ignored value.
-     */
-    public void expectAndDefaultThrow(Object ignored, Throwable throwable) {
-        expectLastCall(
-                "method call on the mock needed before setting default Throwable")
-                .andStubThrow(throwable);
-    }
-
-    private IExpectationSetters<Object> expectLastCall(String failureMessage) {
-        try {
-            return EasyMock.expectLastCall();
-        } catch (IllegalStateException e) {
-            throw new IllegalStateException(failureMessage);
-        }
-    }
-
-    private void callWithConvertedRange(IExpectationSetters<Object> setter, Range range) {
-        if (range == ONE) {
-            setter.once();
-        } else if (range == ONE_OR_MORE) {
-            setter.atLeastOnce();
-        } else if (range == ZERO_OR_MORE) {
-            setter.anyTimes();
-        } else {
-            throw new IllegalArgumentException("Unexpected Range");
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/src/org/easymock/MockType.java b/src/org/easymock/MockType.java
new file mode 100644
index 0000000..029e0fc
--- /dev/null
+++ b/src/org/easymock/MockType.java
@@ -0,0 +1,31 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+/**
+ * Enum describing the 3 possibles kind of mocks
+ * 
+ * @author Henri Tremblay
+ * @since 3.2
+ */
+public enum MockType {
+    /** A nice mock expects recorded calls in any order and returning null for other calls */
+    NICE,
+    /** A default mock expects only recorded calls but in any order */
+    DEFAULT,
+    /** A strict mock expects only recorded calls and they should be replayed in their recorded order */
+    STRICT
+}
diff --git a/src/org/easymock/TestSubject.java b/src/org/easymock/TestSubject.java
new file mode 100644
index 0000000..66d01ef
--- /dev/null
+++ b/src/org/easymock/TestSubject.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation to set on a field so that {@link EasyMockRunner} or {@link EasyMockSupport#injectMocks(Object)}
+ * will inject mocks created with {@link Mock} on its fields.
+ * <p>
+ * See {@link EasyMockSupport#injectMocks(Object)} for the injection rules.
+ *
+ * @author Henri Tremblay
+ * @since 3.2
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+public @interface TestSubject {
+
+}
diff --git a/src/org/easymock/internal/AlwaysMatcher.java b/src/org/easymock/internal/AlwaysMatcher.java
deleted file mode 100644
index 03f52f1..0000000
--- a/src/org/easymock/internal/AlwaysMatcher.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import org.easymock.AbstractMatcher;
-
- at SuppressWarnings("deprecation")
-public class AlwaysMatcher extends AbstractMatcher {
-
-    private static final long serialVersionUID = 592339838132342008L;
-
-    public boolean matches(Object[] expected, Object[] actual) {
-        return true;
-    }
-
-    protected String argumentToString(Object argument) {
-        return "<any>";
-    }
-}
\ No newline at end of file
diff --git a/src/org/easymock/internal/AndroidClassProxyFactory.java b/src/org/easymock/internal/AndroidClassProxyFactory.java
new file mode 100644
index 0000000..da04042
--- /dev/null
+++ b/src/org/easymock/internal/AndroidClassProxyFactory.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.easymock.ConstructorArgs;
+
+import com.google.dexmaker.stock.ProxyBuilder;
+
+// ///CLOVER:OFF (sadly not possible to test android with clover)
+/**
+ * Mocks concrete classes for Android's runtime by generating dex files.
+ */
+public final class AndroidClassProxyFactory implements IProxyFactory {
+    public <T> T createProxy(Class<T> toMock, InvocationHandler handler,
+            Method[] mockedMethods, ConstructorArgs constructorArgs) {
+        final MockHandler interceptor = new MockHandler(handler, mockedMethods);
+        try {
+            ProxyBuilder<T> builder = ProxyBuilder.forClass(toMock)
+                    .handler(interceptor);
+            if (constructorArgs != null) {
+                builder.constructorArgTypes(constructorArgs.getConstructor().getParameterTypes())
+                        .constructorArgValues(constructorArgs.getInitArgs());
+            } else {
+                try {
+                    DefaultClassInstantiator instantiator = new DefaultClassInstantiator();
+                    Constructor<?> constructor = instantiator.getConstructorToUse(toMock);
+                    Object[] params = instantiator.getArgsForTypes(constructor.getParameterTypes());
+                    builder.constructorArgTypes(constructor.getParameterTypes())
+                            .constructorArgValues(params);
+                } catch (InstantiationException e) {
+                    throw new RuntimeException("Fail to instantiate mock for " + toMock);
+                }
+            }
+            return builder.build();
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to mock " + toMock, e);
+        }
+    }
+
+    public InvocationHandler getInvocationHandler(Object mock) {
+        MockHandler mockHandler = (MockHandler) ProxyBuilder.getInvocationHandler(mock);
+        return mockHandler.delegate;
+    }
+
+    private static class MockHandler implements InvocationHandler {
+        private final InvocationHandler delegate;
+        private final Set<Method> mockedMethods;
+
+        public MockHandler(InvocationHandler delegate, Method... mockedMethods) {
+            this.delegate = delegate;
+            this.mockedMethods = (mockedMethods != null)
+                    ? new HashSet<Method>(Arrays.asList(mockedMethods))
+                    : null;
+        }
+
+        public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
+            if (method.isBridge()) {
+                method = BridgeMethodResolver.findBridgedMethod(method);
+            }
+
+            // Never intercept EasyMock's own calls to fillInStackTrace
+            boolean internalFillInStackTraceCall = obj instanceof Throwable
+                    && method.getName().equals("fillInStackTrace")
+                    && ClassProxyFactory.isCallerMockInvocationHandlerInvoke(new Throwable());
+
+            if (internalFillInStackTraceCall
+                    || isMocked(method) && !Modifier.isAbstract(method.getModifiers())) {
+                return ProxyBuilder.callSuper(obj, method, args);
+            }
+
+            return delegate.invoke(obj, method, args);
+        }
+
+        private boolean isMocked(Method method) {
+            return mockedMethods != null && !mockedMethods.contains(method);
+        }
+    }
+}
+// ///CLOVER:ON
\ No newline at end of file
diff --git a/src/org/easymock/internal/AndroidSupport.java b/src/org/easymock/internal/AndroidSupport.java
new file mode 100644
index 0000000..43c683e
--- /dev/null
+++ b/src/org/easymock/internal/AndroidSupport.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * Android-specific support.
+ */
+public final class AndroidSupport {
+    // ///CLOVER:OFF
+    private static boolean isAndroid;
+    static {
+        try {
+            Class.forName("dalvik.system.PathClassLoader");
+            isAndroid = true;
+        } catch (final ClassNotFoundException e) {
+            isAndroid = false;
+        }
+    }
+
+    public static boolean isAndroid() {
+        return isAndroid;
+    }
+    // ///CLOVER:ON    
+}
diff --git a/src/org/easymock/internal/ArgumentToString.java b/src/org/easymock/internal/ArgumentToString.java
new file mode 100644
index 0000000..c1e3c50
--- /dev/null
+++ b/src/org/easymock/internal/ArgumentToString.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.lang.reflect.Array;
+
+/**
+ * Utility class to convert method arguments to Strings
+ * 
+ * @author Henri Tremblay
+ */
+public final class ArgumentToString {
+
+    // ///CLOVER:OFF
+    private ArgumentToString() {
+    }
+
+    // ///CLOVER:ON
+
+    public static void appendArgument(final Object value, final StringBuffer buffer) {
+        if (value == null) {
+            buffer.append("null");
+        } else if (value instanceof String) {
+            buffer.append("\"");
+            buffer.append(value);
+            buffer.append("\"");
+        } else if (value instanceof Character) {
+            buffer.append("'");
+            buffer.append(value);
+            buffer.append("'");
+        } else if (value.getClass().isArray()) {
+            buffer.append("[");
+            for (int i = 0; i < Array.getLength(value); i++) {
+                if (i > 0) {
+                    buffer.append(", ");
+                }
+                appendArgument(Array.get(value, i), buffer);
+            }
+            buffer.append("]");
+        } else {
+            buffer.append(value);
+        }
+    }
+
+    /**
+     * Converts an argument to a String using
+     * {@link #appendArgument(Object, StringBuffer)}
+     * 
+     * @param argument
+     *            the argument to convert to a String.
+     * @return a <code>String</code> representation of the argument.
+     */
+    public static String argumentToString(final Object argument) {
+        final StringBuffer result = new StringBuffer();
+        ArgumentToString.appendArgument(argument, result);
+        return result.toString();
+    }
+
+    /**
+     * Returns a string representation of the arguments. This convenience
+     * implementation calls {@link #argumentToString(Object)} for every argument
+     * in the given array and returns the string representations of the
+     * arguments separated by commas.
+     * 
+     * @param arguments
+     *            the arguments to be used in the string representation.
+     * @return a string representation of the matcher.
+     */
+    public static String argumentsToString(Object... arguments) {
+        if (arguments == null) {
+            arguments = new Object[0];
+        }
+
+        final StringBuilder result = new StringBuilder();
+
+        for (int i = 0; i < arguments.length; i++) {
+            if (i > 0) {
+                result.append(", ");
+            }
+            result.append(argumentToString(arguments[i]));
+        }
+        return result.toString();
+    }
+}
diff --git a/src/org/easymock/internal/ArrayMatcher.java b/src/org/easymock/internal/ArrayMatcher.java
deleted file mode 100644
index c88be58..0000000
--- a/src/org/easymock/internal/ArrayMatcher.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import org.easymock.AbstractMatcher;
-import org.easymock.internal.matchers.ArrayEquals;
-
- at SuppressWarnings("deprecation")
-public class ArrayMatcher extends AbstractMatcher {
-
-    private static final long serialVersionUID = -4594659581004800814L;
-
-    public String argumentToString(Object argument) {
-        StringBuffer result = new StringBuffer();
-        new ArrayEquals(argument).appendTo(result);
-        return result.toString();
-    }
-
-    public boolean argumentMatches(Object expected, Object actual) {
-        return new ArrayEquals(expected).matches(actual);
-    }
-}
\ No newline at end of file
diff --git a/src/org/easymock/internal/AssertionErrorWrapper.java b/src/org/easymock/internal/AssertionErrorWrapper.java
index 17801ec..5c30e07 100644
--- a/src/org/easymock/internal/AssertionErrorWrapper.java
+++ b/src/org/easymock/internal/AssertionErrorWrapper.java
@@ -1,20 +1,34 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-public class AssertionErrorWrapper extends RuntimeException {
-
-    private static final long serialVersionUID = -2087349195182278608L;
-    
-    private final AssertionError error;
-
-    public AssertionErrorWrapper(AssertionError error) {
-        this.error = error;
-    }
-
-    public AssertionError getAssertionError() {
-        return error;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class AssertionErrorWrapper extends RuntimeException {
+
+    private static final long serialVersionUID = -2087349195182278608L;
+
+    private final AssertionError error;
+
+    public AssertionErrorWrapper(final AssertionError error) {
+        this.error = error;
+    }
+
+    public AssertionError getAssertionError() {
+        return error;
+    }
+}
diff --git a/src/org/easymock/internal/BridgeMethodResolver.java b/src/org/easymock/internal/BridgeMethodResolver.java
new file mode 100644
index 0000000..8a8e5d5
--- /dev/null
+++ b/src/org/easymock/internal/BridgeMethodResolver.java
@@ -0,0 +1,444 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Code taken from the <a href="http://www.springframework.org">Spring
+ * framework</a>.
+ * 
+ * Helper for resolving synthetic {@link Method#isBridge bridge Methods} to the
+ * {@link Method} being bridged.
+ * 
+ * <p>
+ * Given a synthetic {@link Method#isBridge bridge Method} returns the
+ * {@link Method} being bridged. A bridge method may be created by the compiler
+ * when extending a parameterized type whose methods have parameterized
+ * arguments. During runtime invocation the bridge {@link Method} may be invoked
+ * and/or used via reflection. When attempting to locate annotations on
+ * {@link Method Methods}, it is wise to check for bridge {@link Method Methods}
+ * as appropriate and find the bridged {@link Method}.
+ * 
+ * <p>
+ * See <a href="http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12.4.5"
+ * > The Java Language Specification</a> for more details on the use of bridge
+ * methods.
+ * 
+ * @author Rob Harrop
+ * @author Juergen Hoeller
+ */
+public final class BridgeMethodResolver {
+
+    // Hard to test all cases since bridges varies from JVM implementation
+    // Plus, the code is taken from Spring so we consider it is working
+    // So, don't check coverage over the class
+
+    // ///CLOVER:OFF
+    private BridgeMethodResolver() {
+    }
+
+    /**
+     * Find the original method for the supplied {@link Method bridge Method}.
+     * <p>
+     * It is safe to call this method passing in a non-bridge {@link Method}
+     * instance. In such a case, the supplied {@link Method} instance is
+     * returned directly to the caller. Callers are <strong>not</strong>
+     * required to check for bridging before calling this method.
+     * 
+     * @param bridgeMethod
+     *            the bridge method
+     * @return the original method for the bridge
+     * @throws IllegalStateException
+     *             if no bridged {@link Method} can be found
+     */
+    public static Method findBridgedMethod(final Method bridgeMethod) {
+        assert bridgeMethod != null : "Method must not be null";
+
+        if (!bridgeMethod.isBridge()) {
+            return bridgeMethod;
+        }
+
+        // Gather all methods with matching name and parameter size.
+        final List<Method> candidateMethods = new ArrayList<Method>();
+        final Method[] methods = getAllDeclaredMethods(bridgeMethod.getDeclaringClass());
+        for (final Method candidateMethod : methods) {
+            if (isBridgedCandidateFor(candidateMethod, bridgeMethod)) {
+                candidateMethods.add(candidateMethod);
+            }
+        }
+
+        Method result;
+        // Now perform simple quick checks.
+        if (candidateMethods.size() == 1) {
+            result = candidateMethods.get(0);
+        } else {
+            result = searchCandidates(candidateMethods, bridgeMethod);
+        }
+
+        if (result == null) {
+            throw new IllegalStateException("Unable to locate bridged method for bridge method '"
+                    + bridgeMethod + "'");
+        }
+
+        return result;
+    }
+
+    /**
+     * Search for the bridged method in the given candidates.
+     * 
+     * @param candidateMethods
+     *            the List of candidate Methods
+     * @param bridgeMethod
+     *            the bridge method
+     * @return the bridged method, or <code>null</code> if none found
+     */
+    private static Method searchCandidates(final List<Method> candidateMethods, final Method bridgeMethod) {
+        final Map<TypeVariable<?>, Type> typeParameterMap = createTypeVariableMap(bridgeMethod
+                .getDeclaringClass());
+        for (int i = 0; i < candidateMethods.size(); i++) {
+            final Method candidateMethod = candidateMethods.get(i);
+            if (isBridgeMethodFor(bridgeMethod, candidateMethod, typeParameterMap)) {
+                return candidateMethod;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return <code>true</code> if the supplied '<code>candidateMethod</code>'
+     * can be consider a validate candidate for the {@link Method} that is
+     * {@link Method#isBridge() bridged} by the supplied {@link Method bridge
+     * Method}. This method performs inexpensive checks and can be used quickly
+     * filter for a set of possible matches.
+     */
+    private static boolean isBridgedCandidateFor(final Method candidateMethod, final Method bridgeMethod) {
+        return (!candidateMethod.isBridge() && !candidateMethod.equals(bridgeMethod)
+                && candidateMethod.getName().equals(bridgeMethod.getName()) && candidateMethod
+                .getParameterTypes().length == bridgeMethod.getParameterTypes().length);
+    }
+
+    /**
+     * Determine whether or not the bridge {@link Method} is the bridge for the
+     * supplied candidate {@link Method}.
+     */
+    private static boolean isBridgeMethodFor(final Method bridgeMethod, final Method candidateMethod,
+            final Map<TypeVariable<?>, Type> typeVariableMap) {
+        if (isResolvedTypeMatch(candidateMethod, bridgeMethod, typeVariableMap)) {
+            return true;
+        }
+        final Method method = findGenericDeclaration(bridgeMethod);
+        return (method != null ? isResolvedTypeMatch(method, candidateMethod, typeVariableMap) : false);
+    }
+
+    /**
+     * Search for the generic {@link Method} declaration whose erased signature
+     * matches that of the supplied bridge method.
+     * 
+     * @throws IllegalStateException
+     *             if the generic declaration cannot be found
+     */
+    private static Method findGenericDeclaration(final Method bridgeMethod) {
+        // Search parent types for method that has same signature as bridge.
+        Class<?> superclass = bridgeMethod.getDeclaringClass().getSuperclass();
+        while (!Object.class.equals(superclass)) {
+            final Method method = searchForMatch(superclass, bridgeMethod);
+            if (method != null && !method.isBridge()) {
+                return method;
+            }
+            superclass = superclass.getSuperclass();
+        }
+
+        // Search interfaces.
+        final Class<?>[] interfaces = getAllInterfacesForClass(bridgeMethod.getDeclaringClass());
+        for (final Class<?> anInterface : interfaces) {
+            final Method method = searchForMatch(anInterface, bridgeMethod);
+            if (method != null && !method.isBridge()) {
+                return method;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return <code>true</code> if the {@link Type} signature of both the
+     * supplied {@link Method#getGenericParameterTypes() generic Method} and
+     * concrete {@link Method} are equal after resolving all
+     * {@link TypeVariable TypeVariables} using the supplied
+     * {@link #createTypeVariableMap TypeVariable Map}, otherwise returns
+     * <code>false</code>.
+     */
+    private static boolean isResolvedTypeMatch(final Method genericMethod, final Method candidateMethod,
+            final Map<TypeVariable<?>, Type> typeVariableMap) {
+        final Type[] genericParameters = genericMethod.getGenericParameterTypes();
+        final Class<?>[] candidateParameters = candidateMethod.getParameterTypes();
+        if (genericParameters.length != candidateParameters.length) {
+            return false;
+        }
+        for (int i = 0; i < genericParameters.length; i++) {
+            final Type genericParameter = genericParameters[i];
+            final Class<?> candidateParameter = candidateParameters[i];
+            if (candidateParameter.isArray()) {
+                // An array type: compare the component type.
+                final Type rawType = getRawType(genericParameter, typeVariableMap);
+                if (rawType instanceof GenericArrayType) {
+                    if (!candidateParameter.getComponentType().equals(
+                            getRawType(((GenericArrayType) rawType).getGenericComponentType(),
+                                    typeVariableMap))) {
+                        return false;
+                    }
+                    break;
+                }
+            }
+            // A non-array type: compare the type itself.
+            if (!candidateParameter.equals(getRawType(genericParameter, typeVariableMap))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Determine the raw type for the given generic parameter type.
+     */
+    private static Type getRawType(final Type genericType, final Map<TypeVariable<?>, Type> typeVariableMap) {
+        if (genericType instanceof TypeVariable<?>) {
+            final TypeVariable<?> tv = (TypeVariable<?>) genericType;
+            final Type result = typeVariableMap.get(tv);
+            return (result != null ? result : Object.class);
+        } else if (genericType instanceof ParameterizedType) {
+            return ((ParameterizedType) genericType).getRawType();
+        } else {
+            return genericType;
+        }
+    }
+
+    /**
+     * If the supplied {@link Class} has a declared {@link Method} whose
+     * signature matches that of the supplied {@link Method}, then this matching
+     * {@link Method} is returned, otherwise <code>null</code> is returned.
+     */
+    private static Method searchForMatch(final Class<?> type, final Method bridgeMethod) {
+        return findMethod(type, bridgeMethod.getName(), bridgeMethod.getParameterTypes());
+    }
+
+    /**
+     * Build a mapping of {@link TypeVariable#getName TypeVariable names} to
+     * concrete {@link Class} for the specified {@link Class}. Searches all
+     * super types, enclosing types and interfaces.
+     */
+    private static Map<TypeVariable<?>, Type> createTypeVariableMap(final Class<?> cls) {
+        final Map<TypeVariable<?>, Type> typeVariableMap = new HashMap<TypeVariable<?>, Type>();
+
+        // interfaces
+        extractTypeVariablesFromGenericInterfaces(cls.getGenericInterfaces(), typeVariableMap);
+
+        // super class
+        Type genericType = cls.getGenericSuperclass();
+        Class<?> type = cls.getSuperclass();
+        while (!Object.class.equals(type)) {
+            if (genericType instanceof ParameterizedType) {
+                final ParameterizedType pt = (ParameterizedType) genericType;
+                populateTypeMapFromParameterizedType(pt, typeVariableMap);
+            }
+            extractTypeVariablesFromGenericInterfaces(type.getGenericInterfaces(), typeVariableMap);
+            genericType = type.getGenericSuperclass();
+            type = type.getSuperclass();
+        }
+
+        // enclosing class
+        type = cls;
+        while (type.isMemberClass()) {
+            genericType = type.getGenericSuperclass();
+            if (genericType instanceof ParameterizedType) {
+                final ParameterizedType pt = (ParameterizedType) genericType;
+                populateTypeMapFromParameterizedType(pt, typeVariableMap);
+            }
+            type = type.getEnclosingClass();
+        }
+
+        return typeVariableMap;
+    }
+
+    private static void extractTypeVariablesFromGenericInterfaces(final Type[] genericInterfaces,
+            final Map<TypeVariable<?>, Type> typeVariableMap) {
+        for (final Type genericInterface : genericInterfaces) {
+            if (genericInterface instanceof ParameterizedType) {
+                final ParameterizedType pt = (ParameterizedType) genericInterface;
+                populateTypeMapFromParameterizedType(pt, typeVariableMap);
+                if (pt.getRawType() instanceof Class<?>) {
+                    extractTypeVariablesFromGenericInterfaces(((Class<?>) pt.getRawType())
+                            .getGenericInterfaces(), typeVariableMap);
+                }
+            } else if (genericInterface instanceof Class<?>) {
+                extractTypeVariablesFromGenericInterfaces(((Class<?>) genericInterface)
+                        .getGenericInterfaces(), typeVariableMap);
+            }
+        }
+    }
+
+    /**
+     * Read the {@link TypeVariable TypeVariables} from the supplied
+     * {@link ParameterizedType} and add mappings corresponding to the
+     * {@link TypeVariable#getName TypeVariable name} -> concrete type to the
+     * supplied {@link Map}.
+     * <p>
+     * Consider this case:
+     * 
+     * <pre class="code>
+     * public interface Foo<S, T> {
+     *  ..
+     * }
+     * 
+     * public class FooImpl implements Foo<String, Integer> {
+     *  ..
+     * }
+     * </pre>
+     * 
+     * For '<code>FooImpl</code>' the following mappings would be added to the
+     * {@link Map}: {S=java.lang.String, T=java.lang.Integer}.
+     */
+    private static void populateTypeMapFromParameterizedType(final ParameterizedType type,
+            final Map<TypeVariable<?>, Type> typeVariableMap) {
+        if (type.getRawType() instanceof Class<?>) {
+            final Type[] actualTypeArguments = type.getActualTypeArguments();
+            final TypeVariable<?>[] typeVariables = ((Class<?>) type.getRawType()).getTypeParameters();
+            for (int i = 0; i < actualTypeArguments.length; i++) {
+                final Type actualTypeArgument = actualTypeArguments[i];
+                final TypeVariable<?> variable = typeVariables[i];
+                if (actualTypeArgument instanceof Class<?>) {
+                    typeVariableMap.put(variable, actualTypeArgument);
+                } else if (actualTypeArgument instanceof GenericArrayType) {
+                    typeVariableMap.put(variable, actualTypeArgument);
+                } else if (actualTypeArgument instanceof ParameterizedType) {
+                    typeVariableMap.put(variable, ((ParameterizedType) actualTypeArgument).getRawType());
+                } else if (actualTypeArgument instanceof TypeVariable<?>) {
+                    // We have a type that is parameterized at instantiation time
+                    // the nearest match on the bridge method will be the bounded type.
+                    final TypeVariable<?> typeVariableArgument = (TypeVariable<?>) actualTypeArgument;
+                    Type resolvedType = typeVariableMap.get(typeVariableArgument);
+                    if (resolvedType == null) {
+                        resolvedType = extractClassForTypeVariable(typeVariableArgument);
+                    }
+                    if (resolvedType != null) {
+                        typeVariableMap.put(variable, resolvedType);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Extracts the bound '<code>Class</code>' for a give {@link TypeVariable}.
+     */
+    private static Class<?> extractClassForTypeVariable(final TypeVariable<?> typeVariable) {
+        final Type[] bounds = typeVariable.getBounds();
+        Type result = null;
+        if (bounds.length > 0) {
+            final Type bound = bounds[0];
+            if (bound instanceof ParameterizedType) {
+                result = ((ParameterizedType) bound).getRawType();
+            } else if (bound instanceof Class<?>) {
+                result = bound;
+            } else if (bound instanceof TypeVariable<?>) {
+                result = extractClassForTypeVariable((TypeVariable<?>) bound);
+            }
+        }
+        return (result instanceof Class<?> ? (Class<?>) result : null);
+    }
+
+    /**
+     * Return all interfaces that the given class implements as array, including
+     * ones implemented by superclasses.
+     * <p>
+     * If the class itself is an interface, it gets returned as sole interface.
+     * 
+     * @param clazz
+     *            the class to analyse for interfaces
+     * @return all interfaces that the given object implements as array
+     */
+    private static Class<?>[] getAllInterfacesForClass(Class<?> clazz) {
+        assert clazz != null : "Class must not be null";
+        if (clazz.isInterface()) {
+            return new Class[] { clazz };
+        }
+        final List<Class<?>> interfaces = new ArrayList<Class<?>>();
+        while (clazz != null) {
+            for (int i = 0; i < clazz.getInterfaces().length; i++) {
+                final Class<?> ifc = clazz.getInterfaces()[i];
+                if (!interfaces.contains(ifc)) {
+                    interfaces.add(ifc);
+                }
+            }
+            clazz = clazz.getSuperclass();
+        }
+        return interfaces.toArray(new Class[interfaces.size()]);
+    }
+
+    /**
+     * Attempt to find a {@link Method} on the supplied class with the supplied
+     * name and parameter types. Searches all superclasses up to
+     * <code>Object</code>.
+     * <p>
+     * Returns <code>null</code> if no {@link Method} can be found.
+     * 
+     * @param clazz
+     *            the class to introspect
+     * @param name
+     *            the name of the method
+     * @param paramTypes
+     *            the parameter types of the method
+     * @return the Method object, or <code>null</code> if none found
+     */
+    private static Method findMethod(final Class<?> clazz, final String name, final Class<?>[] paramTypes) {
+        assert clazz != null : "Class must not be null";
+        assert name != null : "Method name must not be null";
+        Class<?> searchType = clazz;
+        while (!Object.class.equals(searchType) && searchType != null) {
+            final Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType
+                    .getDeclaredMethods());
+            for (final Method method : methods) {
+                if (name.equals(method.getName()) && Arrays.equals(paramTypes, method.getParameterTypes())) {
+                    return method;
+                }
+            }
+            searchType = searchType.getSuperclass();
+        }
+        return null;
+    }
+
+    /**
+     * Get all declared methods on the leaf class and all superclasses. Leaf
+     * class methods are included first.
+     */
+    private static Method[] getAllDeclaredMethods(Class<?> leafClass) {
+        final List<Method> list = new LinkedList<Method>();
+
+        // Keep backing up the inheritance hierarchy.
+        do {
+            final Method[] methods = leafClass.getDeclaredMethods();
+            for (final Method method : methods) {
+                list.add(method);
+            }
+            leafClass = leafClass.getSuperclass();
+        } while (leafClass != null);
+
+        return list.toArray(new Method[list.size()]);
+    }
+    // ///CLOVER:ON
+}
diff --git a/src/org/easymock/internal/ClassInstantiatorFactory.java b/src/org/easymock/internal/ClassInstantiatorFactory.java
new file mode 100644
index 0000000..0bea8db
--- /dev/null
+++ b/src/org/easymock/internal/ClassInstantiatorFactory.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * Factory returning a {@link IClassInstantiator}for the current JVM
+ * 
+ * @author Henri Tremblay
+ */
+public final class ClassInstantiatorFactory {
+
+    private static IClassInstantiator instantiator = new ObjenesisClassInstantiator();
+
+    // ///CLOVER:OFF
+    private ClassInstantiatorFactory() {
+    }
+
+    // ///CLOVER:ON
+
+    /**
+     * Returns the current JVM as specified in the System properties
+     * 
+     * @return current JVM
+     */
+    public static String getJVM() {
+        return System.getProperty("java.vm.vendor");
+    }
+
+    /**
+     * Returns the current JVM specification version (1.5, 1.4, 1.3)
+     * 
+     * @return current JVM specification version
+     */
+    public static String getJVMSpecificationVersion() {
+        return System.getProperty("java.specification.version");
+    }
+
+    public static boolean is1_3Specifications() {
+        return getJVMSpecificationVersion().equals("1.3");
+    }
+
+    /**
+     * Returns a class instantiator suitable for the current JVM
+     * 
+     * @return a class instantiator usable on the current JVM
+     */
+    public static IClassInstantiator getInstantiator() {
+        return instantiator;
+    }
+
+    /**
+     * Allow to override the default instantiator. Useful when the default one
+     * isn't able to create mocks in a given environment.
+     * 
+     * @param i
+     *            New instantiator
+     */
+    public static void setInstantiator(final IClassInstantiator i) {
+        instantiator = i;
+    }
+
+    /**
+     * Set back the default instantiator
+     */
+    public static void setDefaultInstantiator() {
+        instantiator = new ObjenesisClassInstantiator();
+    }
+}
diff --git a/src/org/easymock/internal/ClassProxyFactory.java b/src/org/easymock/internal/ClassProxyFactory.java
new file mode 100644
index 0000000..a90f2a7
--- /dev/null
+++ b/src/org/easymock/internal/ClassProxyFactory.java
@@ -0,0 +1,285 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.easymock.ConstructorArgs;
+
+import net.sf.cglib.core.CodeGenerationException;
+import net.sf.cglib.core.CollectionUtils;
+import net.sf.cglib.core.DefaultNamingPolicy;
+import net.sf.cglib.core.NamingPolicy;
+import net.sf.cglib.core.Predicate;
+import net.sf.cglib.core.VisibilityPredicate;
+import net.sf.cglib.proxy.Callback;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.Factory;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
+
+/**
+ * Factory generating a mock for a class.
+ * 
+ * @author Henri Tremblay
+ */
+public class ClassProxyFactory implements IProxyFactory {
+
+    public static class MockMethodInterceptor implements MethodInterceptor, Serializable {
+
+        private static final long serialVersionUID = -9054190871232972342L;
+
+        private final InvocationHandler handler;
+
+        private transient Set<Method> mockedMethods;
+
+        public MockMethodInterceptor(final InvocationHandler handler) {
+            this.handler = handler;
+        }
+
+        public Object intercept(final Object obj, Method method, final Object[] args, final MethodProxy proxy)
+                throws Throwable {
+
+            // We conveniently mock abstract methods be default
+            if (Modifier.isAbstract(method.getModifiers())) {
+                return handler.invoke(obj, method, args);
+            }
+
+            // Here I need to check if the fillInStackTrace was called by EasyMock inner code
+            // If it's the case, just ignore the call. We ignore it for two reasons
+            // 1- In Java 7, the fillInStackTrace won't work because, since no constructor was called, the stackTrace attribute is null
+            // 2- There might be some unexpected side effect in the original fillInStackTrace. So it seems more logical to ignore the call 
+            if (obj instanceof Throwable && method.getName().equals("fillInStackTrace")) {
+                if(isCallerMockInvocationHandlerInvoke(new Throwable())) {
+                        return obj;
+                }
+            }
+
+            // Bridges should delegate to their bridged method. It should be done before
+            // checking for mocked methods because only unbridged method are mocked
+            // It also make sure the method passed to the handler is not the bridge. Normally it
+            // shouldn't be necessary because bridges are never mocked so are never in the mockedMethods
+            // map. So the normal case is that is will call invokeSuper which will call the interceptor for
+            // the bridged method. The problem is that it doesn't happen. It looks like a cglib bug. For
+            // package scoped bridges (see GenericTest), the interceptor is not called for the bridged
+            // method. Not normal from my point of view.
+            if (method.isBridge()) {
+                method = BridgeMethodResolver.findBridgedMethod(method);
+            }
+
+            if (mockedMethods != null && !mockedMethods.contains(method)) {
+                return proxy.invokeSuper(obj, args);
+            }
+
+            return handler.invoke(obj, method, args);
+        }
+
+        public void setMockedMethods(final Method... mockedMethods) {
+            this.mockedMethods = new HashSet<Method>(Arrays.asList(mockedMethods));
+        }
+
+        @SuppressWarnings("unchecked")
+        private void readObject(final java.io.ObjectInputStream stream) throws IOException,
+                ClassNotFoundException {
+            stream.defaultReadObject();
+            final Set<MethodSerializationWrapper> methods = (Set<MethodSerializationWrapper>) stream
+                    .readObject();
+            if (methods == null) {
+                return;
+            }
+
+            mockedMethods = new HashSet<Method>(methods.size());
+            for (final MethodSerializationWrapper m : methods) {
+                try {
+                    mockedMethods.add(m.getMethod());
+                } catch (final NoSuchMethodException e) {
+                    // ///CLOVER:OFF
+                    throw new IOException(e.toString());
+                    // ///CLOVER:ON
+                }
+            }
+        }
+
+        private void writeObject(final java.io.ObjectOutputStream stream) throws IOException {
+            stream.defaultWriteObject();
+
+            if (mockedMethods == null) {
+                stream.writeObject(null);
+                return;
+            }
+
+            final Set<MethodSerializationWrapper> methods = new HashSet<MethodSerializationWrapper>(
+                    mockedMethods.size());
+            for (final Method m : mockedMethods) {
+                methods.add(new MethodSerializationWrapper(m));
+            }
+
+            stream.writeObject(methods);
+        }
+    }
+
+    // ///CLOVER:OFF (I don't know how to test it automatically yet)
+    private static final NamingPolicy ALLOWS_MOCKING_CLASSES_IN_SIGNED_PACKAGES = new DefaultNamingPolicy() {
+        @Override
+        public String getClassName(final String prefix, final String source, final Object key,
+                final Predicate names) {
+            return "codegen." + super.getClassName(prefix, source, key, names);
+        }
+    };
+
+    // ///CLOVER:ON
+
+    public static boolean isCallerMockInvocationHandlerInvoke(final Throwable e) throws Throwable {
+        final StackTraceElement[] elements = e.getStackTrace();
+        return elements.length > 2
+                && elements[2].getClassName().equals(MockInvocationHandler.class.getName())
+                && elements[2].getMethodName().equals("invoke");
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T createProxy(final Class<T> toMock, final InvocationHandler handler,
+            final Method[] mockedMethods, final ConstructorArgs args) {
+        final Enhancer enhancer = createEnhancer(toMock);
+
+        final MockMethodInterceptor interceptor = new MockMethodInterceptor(handler);
+        if (mockedMethods != null) {
+            interceptor.setMockedMethods(mockedMethods);
+        }
+        enhancer.setCallbackType(interceptor.getClass());
+
+        Class<?> mockClass;
+        try {
+            mockClass = enhancer.createClass();
+        } catch (final CodeGenerationException e) {
+            // ///CLOVER:OFF (don't know how to test it automatically)
+            // Probably caused by a NoClassDefFoundError, let's try EasyMock class loader
+            // instead of the default one (which is the class to mock one
+            // This is required by Eclipse Plug-ins, the mock class loader doesn't see
+            // cglib most of the time. Using EasyMock class loader solves this
+            // See issue ID: 2994002
+            enhancer.setClassLoader(getClass().getClassLoader());
+            mockClass = enhancer.createClass();
+            // ///CLOVER:ON
+        }
+
+        try {
+            Enhancer.registerCallbacks(mockClass, new Callback[] { interceptor });
+
+            if (args != null) {
+                // Really instantiate the class
+                Constructor<?> cstr;
+                try {
+                    // Get the constructor with the same params
+                    cstr = mockClass.getDeclaredConstructor(args.getConstructor().getParameterTypes());
+                } catch (final NoSuchMethodException e) {
+                    // Shouldn't happen, constructor is checked when ConstructorArgs is instantiated
+                    // ///CLOVER:OFF
+                    throw new RuntimeException("Fail to find constructor for param types", e);
+                    // ///CLOVER:ON
+                }
+                T mock;
+                try {
+                    cstr.setAccessible(true); // So we can call a protected
+                    // constructor
+                    mock = (T) cstr.newInstance(args.getInitArgs());
+                } catch (final InstantiationException e) {
+                    // ///CLOVER:OFF
+                    throw new RuntimeException("Failed to instantiate mock calling constructor", e);
+                    // ///CLOVER:ON
+                } catch (final IllegalAccessException e) {
+                    // ///CLOVER:OFF
+                    throw new RuntimeException("Failed to instantiate mock calling constructor", e);
+                    // ///CLOVER:ON
+                } catch (final InvocationTargetException e) {
+                    throw new RuntimeException(
+                            "Failed to instantiate mock calling constructor: Exception in constructor",
+                            e.getTargetException());
+                }
+                return mock;
+            } else {
+                // Do not call any constructor
+
+                Factory mock;
+                try {
+                    mock = (Factory) ClassInstantiatorFactory.getInstantiator().newInstance(mockClass);
+                } catch (final InstantiationException e) {
+                    // ///CLOVER:OFF
+                    throw new RuntimeException("Fail to instantiate mock for " + toMock + " on "
+                            + ClassInstantiatorFactory.getJVM() + " JVM");
+                    // ///CLOVER:ON
+                }
+
+                // This call is required. CGlib has some "magic code" making sure a
+                // callback is used by only one instance of a given class. So only
+                // the
+                // instance created right after registering the callback will get
+                // it.
+                // However, this is done in the constructor which I'm bypassing to
+                // allow class instantiation without calling a constructor.
+                // Fortunately, the "magic code" is also called in getCallback which
+                // is
+                // why I'm calling it here mock.getCallback(0);
+                mock.getCallback(0);
+
+                return (T) mock;
+            }
+        } finally {
+            // To avoid CGLib out of memory issues
+            Enhancer.registerCallbacks(mockClass, null);
+        }
+    }
+
+    private Enhancer createEnhancer(final Class<?> toMock) {
+        // Create the mock
+        final Enhancer enhancer = new Enhancer() {
+
+            /**
+             * Filter all private constructors but do not check that there are
+             * some left
+             */
+            @SuppressWarnings("rawtypes")
+            @Override
+            protected void filterConstructors(final Class sc, final List constructors) {
+                CollectionUtils.filter(constructors, new VisibilityPredicate(sc, true));
+            }
+        };
+        enhancer.setSuperclass(toMock);
+
+        // ///CLOVER:OFF (I don't know how to test it automatically yet)
+        // See issue ID: 2994002
+        if (toMock.getSigners() != null) {
+            enhancer.setNamingPolicy(ALLOWS_MOCKING_CLASSES_IN_SIGNED_PACKAGES);
+        }
+        // ///CLOVER:ON
+
+        return enhancer;
+    }
+
+    public InvocationHandler getInvocationHandler(final Object mock) {
+        final Factory factory = (Factory) mock;
+        return ((MockMethodInterceptor) factory.getCallback(0)).handler;
+    }
+}
diff --git a/src/org/easymock/internal/DefaultClassInstantiator.java b/src/org/easymock/internal/DefaultClassInstantiator.java
new file mode 100644
index 0000000..aa64a9b
--- /dev/null
+++ b/src/org/easymock/internal/DefaultClassInstantiator.java
@@ -0,0 +1,206 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.*;
+import java.lang.reflect.*;
+
+import org.easymock.EasyMock;
+
+/**
+ * Default class instantiator that is pretty limited. It just hope that the
+ * mocked class has a public empty constructor.
+ * 
+ * @author Henri Tremblay
+ */
+public class DefaultClassInstantiator implements IClassInstantiator {
+
+    /**
+     * Try to instantiate a class without using a special constructor. See
+     * documentation for the algorithm.
+     * 
+     * @param c
+     *            Class to instantiate
+     */
+    public Object newInstance(final Class<?> c) throws InstantiationException {
+
+        if (isSerializable(c)) {
+            try {
+                return readObject(getSerializedBytes(c));
+                // ///CLOVER:OFF
+            } catch (final IOException e) {
+                throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: ", e);
+            } catch (final ClassNotFoundException e) {
+                throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: ", e);
+            }
+            // ///CLOVER:ON
+        }
+
+        final Constructor<?> constructor = getConstructorToUse(c);
+        final Object[] params = getArgsForTypes(constructor.getParameterTypes());
+        try {
+            return constructor.newInstance(params);
+            // ///CLOVER:OFF
+        } catch (final IllegalArgumentException e) {
+            throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: ", e);
+        } catch (final IllegalAccessException e) {
+            throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: ", e);
+            // ///CLOVER:ON
+        } catch (final InvocationTargetException e) {
+            throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: ", e);
+        }
+    }
+
+    /**
+     * Tells if the provided class is serializable
+     * 
+     * @param clazz
+     *            Class to check
+     * @return If the class is serializable
+     */
+    private boolean isSerializable(final Class<?> clazz) {
+        return Serializable.class.isAssignableFrom(clazz);
+    }
+
+    /**
+     * Return the constructor considered the best to use with this class.
+     * Algorithm is: No args constructor and then first constructor defined in
+     * the class
+     * 
+     * @param clazz
+     *            Class in which constructor is searched
+     * @return Constructor to use
+     */
+    public Constructor<?> getConstructorToUse(final Class<?> clazz) {
+        // First try to use the empty constructor
+        try {
+            return clazz.getConstructor(new Class[0]);
+        } catch (final NoSuchMethodException e) {
+            // If it fails just use the first one
+            if (clazz.getConstructors().length == 0) {
+                throw new IllegalArgumentException("No visible constructors in class " + clazz.getName());
+            }
+            return clazz.getConstructors()[0];
+        }
+    }
+
+    /**
+     * Get some default instances of provided classes
+     * 
+     * @param methodTypes
+     *            Classes to instantiate
+     * @return Instances of methodTypes in order
+     * @throws InstantiationException Thrown if the class instantiation fails
+     */
+    public Object[] getArgsForTypes(final Class<?>[] methodTypes) throws InstantiationException {
+        final Object[] methodArgs = new Object[methodTypes.length];
+
+        for (int i = 0; i < methodTypes.length; i++) {
+
+            if (methodTypes[i].isPrimitive()) {
+                // Return a nice wrapped primitive type
+                methodArgs[i] = RecordState.emptyReturnValueFor(methodTypes[i]);
+            // ///CLOVER:OFF TODO: Remove when we manage to fix the ignored tests
+            } else if (Modifier.isFinal(methodTypes[i].getModifiers())) {
+                // Instantiate the class using the best constructor we can find
+                // (because it's not
+                // possible to mock a final class)
+                methodArgs[i] = newInstance(methodTypes[i]);
+                // ///CLOVER:ON
+            } else {
+                // For all classes and interfaces, just return a nice mock
+                final Object mock = EasyMock.createNiceMock(methodTypes[i]);
+                EasyMock.replay(mock);
+                methodArgs[i] = mock;
+            }
+        }
+        return methodArgs;
+    }
+
+    private static byte[] getSerializedBytes(final Class<?> clazz) throws IOException {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        final DataOutputStream data = new DataOutputStream(baos);
+        data.writeShort(ObjectStreamConstants.STREAM_MAGIC);
+        data.writeShort(ObjectStreamConstants.STREAM_VERSION);
+        data.writeByte(ObjectStreamConstants.TC_OBJECT);
+        data.writeByte(ObjectStreamConstants.TC_CLASSDESC);
+        data.writeUTF(clazz.getName());
+
+        final Long suid = getSerializableUID(clazz);
+
+        data.writeLong(suid.longValue());
+
+        data.writeByte(2); // classDescFlags (2 = Serializable)
+        data.writeShort(0); // field count
+        data.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
+        data.writeByte(ObjectStreamConstants.TC_NULL);
+        return baos.toByteArray();
+    }
+
+    private static Long getSerializableUID(final Class<?> clazz) {
+
+        try {
+            final Field f = clazz.getDeclaredField("serialVersionUID");
+            final int mask = Modifier.STATIC | Modifier.FINAL;
+            if ((f.getModifiers() & mask) == mask) {
+                f.setAccessible(true);
+                return Long.valueOf(f.getLong(null));
+            }
+        } catch (final NoSuchFieldException e) {
+            // It's not there, compute it then
+        } catch (final IllegalAccessException e) {
+            // ///CLOVER:OFF
+            throw new RuntimeException("Should have been able to get serialVersionUID since it's there");
+            // ///CLOVER:ON
+        }
+        // ///CLOVER:OFF
+        return callLongMethod(clazz,
+                ClassInstantiatorFactory.is1_3Specifications() ? "computeSerialVersionUID"
+                        : "computeDefaultSUID");
+        // ///CLOVER:ON
+    }
+
+    private static Long callLongMethod(final Class<?> clazz, final String methodName) {
+
+        Method method;
+        // ///CLOVER:OFF
+        try {
+            method = ObjectStreamClass.class.getDeclaredMethod(methodName, new Class[] { Class.class });
+        } catch (final NoSuchMethodException e) {
+            throw new InternalError("ObjectStreamClass." + methodName + " seems to have vanished");
+        }
+        final boolean accessible = method.isAccessible();
+        method.setAccessible(true);
+        Long suid;
+        try {
+            suid = (Long) method.invoke(null, new Object[] { clazz });
+        } catch (final IllegalAccessException e) {
+            throw new InternalError("ObjectStreamClass." + methodName + " should have been accessible");
+        } catch (final InvocationTargetException e) {
+            throw new InternalError("ObjectStreamClass." + methodName + " failled to be called: "
+                    + e.getMessage());
+        }
+        method.setAccessible(accessible);
+        // ///CLOVER:ON
+        return suid;
+    }
+
+    private static Object readObject(final byte[] bytes) throws IOException, ClassNotFoundException {
+        final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
+        return in.readObject();
+    }
+
+}
diff --git a/src/org/easymock/internal/EasyMockProperties.java b/src/org/easymock/internal/EasyMockProperties.java
new file mode 100644
index 0000000..e1922a2
--- /dev/null
+++ b/src/org/easymock/internal/EasyMockProperties.java
@@ -0,0 +1,139 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * Contains properties used by EasyMock to change its default behavior. The
+ * loading order is (any step being able to overload the properties of the
+ * previous step):
+ * <ul>
+ * <li>easymock.properties in classpath default package</li>
+ * <li>explicit call to setProperty</li>
+ * </ul>
+ * 
+ * @author Henri Tremblay
+ */
+public final class EasyMockProperties {
+
+    private static final String PREFIX = "easymock.";
+
+    // volatile for double-checked locking
+    private static volatile EasyMockProperties instance;
+
+    private final Properties properties = new Properties();
+
+    public static EasyMockProperties getInstance() {
+        if (instance == null) {
+            synchronized (EasyMockProperties.class) {
+                // ///CLOVER:OFF
+                if (instance == null) {
+                    // ///CLOVER:ON
+                    instance = new EasyMockProperties();
+                }
+            }
+        }
+        return instance;
+    }
+
+    private EasyMockProperties() {
+        loadEasyMockProperties("easymock.properties");
+    }
+
+    private void loadEasyMockProperties(final String propertyFileName) {
+        InputStream in = getClassLoader().getResourceAsStream(propertyFileName);
+        if (in != null) {
+            in = new BufferedInputStream(in);
+            try {
+                properties.load(in);
+            } catch (final IOException e) {
+                throw new RuntimeException("Failed to read " + propertyFileName + " file");
+            } finally {
+                try {
+                    in.close();
+                } catch (final IOException e) {
+                    // Doesn't matter
+                }
+            }
+        }
+    }
+
+    /**
+     * Searches for the property with the specified key. If the key is not
+     * found, return the default value.
+     * 
+     * @param key
+     *            key leading to the property
+     * @param defaultValue
+     *            the value to be returned if the key isn't found
+     * @return the value found for the key or the default value
+     */
+    public String getProperty(final String key, final String defaultValue) {
+        return properties.getProperty(key, defaultValue);
+    }
+
+    /**
+     * Searches for the property with the specified key. Return null if the key
+     * is not found.
+     * 
+     * @param key
+     *            key leading to the property
+     * @return the value found for the key or null
+     */
+    public String getProperty(final String key) {
+        return properties.getProperty(key);
+    }
+
+    /**
+     * Add a value referenced by the provided key. A null value will remove the
+     * key
+     * 
+     * @param key
+     *            the key of the new property
+     * @param value
+     *            the value corresponding to <tt>key</tt>.
+     * @return the property previous value
+     */
+    public String setProperty(final String key, final String value) {
+        if (!key.startsWith(PREFIX)) {
+            throw new IllegalArgumentException("Invalid key (" + key
+                    + "), an easymock property starts with \"" + PREFIX + "\"");
+        }
+        if (value == null) {
+            return (String) properties.remove(key);
+        }
+        return (String) properties.setProperty(key, value);
+    }
+
+    private ClassLoader getClassLoader() {
+        ClassLoader cl = null;
+        try {
+            cl = Thread.currentThread().getContextClassLoader();
+        } catch (final Throwable ex) {
+            // Cannot access thread context ClassLoader - falling back to system
+            // class loader
+        }
+        if (cl == null) {
+            // No thread context class loader -> use class loader of this class.
+            cl = getClass().getClassLoader();
+        }
+        return cl;
+    }
+}
diff --git a/src/org/easymock/internal/EqualsMatcher.java b/src/org/easymock/internal/EqualsMatcher.java
deleted file mode 100644
index 5063fa2..0000000
--- a/src/org/easymock/internal/EqualsMatcher.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import org.easymock.AbstractMatcher;
-
- at SuppressWarnings("deprecation")
-public class EqualsMatcher extends AbstractMatcher {
-
-    private static final long serialVersionUID = 4152805764785966978L;
-}
\ No newline at end of file
diff --git a/src/org/easymock/internal/ErrorMessage.java b/src/org/easymock/internal/ErrorMessage.java
new file mode 100644
index 0000000..6950d78
--- /dev/null
+++ b/src/org/easymock/internal/ErrorMessage.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ErrorMessage {
+
+    private final boolean matching;
+
+    private final String message;
+
+    private final int actualCount;
+
+    public ErrorMessage(final boolean matching, final String message, final int actualCount) {
+        this.matching = matching;
+        this.message = message;
+        this.actualCount = actualCount;
+    }
+
+    public boolean isMatching() {
+        return matching;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public int getActualCount() {
+        return actualCount;
+    }
+
+    public void appendTo(final StringBuilder buffer, final int matches) {
+        buffer.append("\n    ").append(message).append(", actual: ");
+        if (matching) {
+            if (matches == 1) {
+                buffer.append(getActualCount() + 1);
+            } else {
+                buffer.append(getActualCount());
+                buffer.append(" (+1)");
+            }
+        } else {
+            buffer.append(getActualCount());
+        }
+    }
+}
diff --git a/src/org/easymock/internal/ExpectedInvocation.java b/src/org/easymock/internal/ExpectedInvocation.java
index cec515e..1d3337d 100644
--- a/src/org/easymock/internal/ExpectedInvocation.java
+++ b/src/org/easymock/internal/ExpectedInvocation.java
@@ -1,122 +1,119 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.easymock.IArgumentMatcher;
-import org.easymock.internal.matchers.Equals;
-
-public class ExpectedInvocation implements Serializable {
-
-    private static final long serialVersionUID = -5554816464613350531L;
-
-    private final Invocation invocation;
-
-    @SuppressWarnings("deprecation")
-    private final org.easymock.ArgumentsMatcher matcher;
-
-    private final List<IArgumentMatcher> matchers;
-
-    public ExpectedInvocation(Invocation invocation,
-            List<IArgumentMatcher> matchers) {
-        this(invocation, matchers, null);
-    }
-
-    private ExpectedInvocation(Invocation invocation,
-            List<IArgumentMatcher> matchers, @SuppressWarnings("deprecation")
-            org.easymock.ArgumentsMatcher matcher) {
-        this.invocation = invocation;
-        this.matcher = matcher;
-        this.matchers = (matcher == null) ? createMissingMatchers(invocation,
-                matchers) : null;
-    }
-
-    private List<IArgumentMatcher> createMissingMatchers(Invocation invocation,
-            List<IArgumentMatcher> matchers) {
-        if (matchers != null) {
-            if (matchers.size() != invocation.getArguments().length) {
-                throw new IllegalStateException(""
-                        + invocation.getArguments().length
-                        + " matchers expected, " + matchers.size()
-                        + " recorded.");
-            }
-            ;
-            return matchers;
-        }
-        List<IArgumentMatcher> result = new ArrayList<IArgumentMatcher>();
-        for (Object argument : invocation.getArguments()) {
-            result.add(new Equals(argument));
-        }
-        return result;
-    }
-
-    public boolean equals(Object o) {
-        if (o == null || !this.getClass().equals(o.getClass()))
-            return false;
-
-        ExpectedInvocation other = (ExpectedInvocation) o;
-        return this.invocation.equals(other.invocation)
-                && ((this.matcher == null && other.matcher == null) || (this.matcher != null && this.matcher
-                        .equals(other.matcher)))
-                && ((this.matchers == null && other.matchers == null) || (this.matchers != null && this.matchers
-                        .equals(other.matchers)));
-    }
-
-    public int hashCode() {
-        return invocation.hashCode();
-    }
-
-    public boolean matches(Invocation actual) {
-        return matchers != null ? this.invocation.getMock().equals(
-                actual.getMock())
-                && this.invocation.getMethod().equals(actual.getMethod())
-                && matches(actual.getArguments()) : this.invocation.matches(
-                actual, matcher);
-    }
-
-    private boolean matches(Object[] arguments) {
-        if (arguments.length != matchers.size()) {
-            return false;
-        }
-        for (int i = 0; i < arguments.length; i++) {
-            if (!matchers.get(i).matches(arguments[i])) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public String toString() {
-        return matchers != null ? myToString() : invocation.toString(matcher);
-    }
-
-    private String myToString() {
-        StringBuffer result = new StringBuffer();
-        result.append(invocation.getMockAndMethodName());
-        result.append("(");
-        for (Iterator<IArgumentMatcher> it = matchers.iterator(); it.hasNext();) {
-            it.next().appendTo(result);
-            if (it.hasNext()) {
-                result.append(", ");
-            }
-        }
-        result.append(")");
-        return result.toString();
-    }
-
-    public Method getMethod() {
-        return invocation.getMethod();
-    }
-
-    public ExpectedInvocation withMatcher(@SuppressWarnings("deprecation")
-    org.easymock.ArgumentsMatcher matcher) {
-        return new ExpectedInvocation(invocation, null, matcher);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.easymock.IArgumentMatcher;
+import org.easymock.internal.matchers.Equals;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ExpectedInvocation implements Serializable {
+
+    private static final long serialVersionUID = -5554816464613350531L;
+
+    private final Invocation invocation;
+
+    private final List<IArgumentMatcher> matchers;
+
+    public ExpectedInvocation(final Invocation invocation, final List<IArgumentMatcher> matchers) {
+        this.invocation = invocation;
+        this.matchers = createMissingMatchers(invocation, matchers);
+    }
+
+    private List<IArgumentMatcher> createMissingMatchers(final Invocation invocation,
+            final List<IArgumentMatcher> matchers) {
+        if (matchers != null) {
+            if (matchers.size() != invocation.getArguments().length) {
+                throw new IllegalStateException(
+                        ""
+                                + invocation.getArguments().length
+                                + " matchers expected, "
+                                + matchers.size()
+                                + " recorded.\n"
+                                + "This exception usually occurs when matchers are mixed with raw values when recording a method:\n"
+                                + "\tfoo(5, eq(6));\t// wrong\n"
+                                + "You need to use no matcher at all or a matcher for every single param:\n"
+                                + "\tfoo(eq(5), eq(6));\t// right\n" + "\tfoo(5, 6);\t// also right");
+            }
+            return matchers;
+        }
+        final List<IArgumentMatcher> result = new ArrayList<IArgumentMatcher>();
+        for (final Object argument : invocation.getArguments()) {
+            result.add(new Equals(argument));
+        }
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (o == null || !this.getClass().equals(o.getClass())) {
+            return false;
+        }
+
+        final ExpectedInvocation other = (ExpectedInvocation) o;
+        return this.invocation.equals(other.invocation)
+                && ((this.matchers == null && other.matchers == null) || (this.matchers != null && this.matchers
+                        .equals(other.matchers)));
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("hashCode() is not implemented");
+    }
+
+    public boolean matches(final Invocation actual) {
+        return this.invocation.getMock().equals(actual.getMock())
+                && this.invocation.getMethod().equals(actual.getMethod()) && matches(actual.getArguments());
+    }
+
+    private boolean matches(final Object[] arguments) {
+        if (arguments.length != matchers.size()) {
+            return false;
+        }
+        for (int i = 0; i < arguments.length; i++) {
+            if (!matchers.get(i).matches(arguments[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer result = new StringBuffer();
+        result.append(invocation.getMockAndMethodName());
+        result.append("(");
+        for (final Iterator<IArgumentMatcher> it = matchers.iterator(); it.hasNext();) {
+            it.next().appendTo(result);
+            if (it.hasNext()) {
+                result.append(", ");
+            }
+        }
+        result.append(")");
+        return result.toString();
+    }
+
+    public Method getMethod() {
+        return invocation.getMethod();
+    }
+}
diff --git a/src/org/easymock/internal/ExpectedInvocationAndResult.java b/src/org/easymock/internal/ExpectedInvocationAndResult.java
index b7c631e..5505c20 100644
--- a/src/org/easymock/internal/ExpectedInvocationAndResult.java
+++ b/src/org/easymock/internal/ExpectedInvocationAndResult.java
@@ -1,30 +1,43 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-
-public class ExpectedInvocationAndResult implements Serializable {
-
-    private static final long serialVersionUID = -1951159588262854559L;
-
-    ExpectedInvocation expectedInvocation;
-
-    Result result;
-
-    public ExpectedInvocationAndResult(ExpectedInvocation expectedInvocation,
-            Result result) {
-        this.expectedInvocation = expectedInvocation;
-        this.result = result;
-    }
-
-    public ExpectedInvocation getExpectedInvocation() {
-        return expectedInvocation;
-    }
-
-    public Result getResult() {
-        return result;
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ExpectedInvocationAndResult implements Serializable {
+
+    private static final long serialVersionUID = -1951159588262854559L;
+
+    private final ExpectedInvocation expectedInvocation;
+
+    private final Result result;
+
+    public ExpectedInvocationAndResult(final ExpectedInvocation expectedInvocation, final Result result) {
+        this.expectedInvocation = expectedInvocation;
+        this.result = result;
+    }
+
+    public ExpectedInvocation getExpectedInvocation() {
+        return expectedInvocation;
+    }
+
+    public Result getResult() {
+        return result;
+    }
 }
\ No newline at end of file
diff --git a/src/org/easymock/internal/ExpectedInvocationAndResults.java b/src/org/easymock/internal/ExpectedInvocationAndResults.java
index 3d5b1c3..0cab01a 100644
--- a/src/org/easymock/internal/ExpectedInvocationAndResults.java
+++ b/src/org/easymock/internal/ExpectedInvocationAndResults.java
@@ -1,35 +1,48 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-
-public class ExpectedInvocationAndResults implements Serializable {
-    
-    private static final long serialVersionUID = 8189985418895395472L;
-
-    ExpectedInvocation expectedInvocation;
-
-    Results results;
-
-    public ExpectedInvocationAndResults(ExpectedInvocation expectedInvocation,
-            Results results) {
-        this.expectedInvocation = expectedInvocation;
-        this.results = results;
-    }
-
-    public ExpectedInvocation getExpectedInvocation() {
-        return expectedInvocation;
-    }
-
-    public Results getResults() {
-        return results;
-    }
-
-    @Override
-    public String toString() {
-        return expectedInvocation.toString() + ": " + results.toString();
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ExpectedInvocationAndResults implements Serializable {
+
+    private static final long serialVersionUID = 8189985418895395472L;
+
+    private final ExpectedInvocation expectedInvocation;
+
+    private final Results results;
+
+    public ExpectedInvocationAndResults(final ExpectedInvocation expectedInvocation, final Results results) {
+        this.expectedInvocation = expectedInvocation;
+        this.results = results;
+    }
+
+    public ExpectedInvocation getExpectedInvocation() {
+        return expectedInvocation;
+    }
+
+    public Results getResults() {
+        return results;
+    }
+
+    @Override
+    public String toString() {
+        return expectedInvocation.toString() + ": " + results.toString();
+    }
 }
\ No newline at end of file
diff --git a/src/org/easymock/internal/IClassInstantiator.java b/src/org/easymock/internal/IClassInstantiator.java
new file mode 100644
index 0000000..c4163b9
--- /dev/null
+++ b/src/org/easymock/internal/IClassInstantiator.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * Used to instantiate a given class.
+ * 
+ * @author Henri Tremblay
+ */
+public interface IClassInstantiator {
+
+    /**
+     * Return a new instance of the specified class. The recommended way is
+     * without calling any constructor. This is usually done by doing like
+     * <code>ObjectInputStream.readObject()</code> which is JVM specific.
+     * 
+     * @param clazz
+     *            class to instantiate
+     * @return new instance of clazz
+     * @throws InstantiationException
+     */
+    Object newInstance(Class<?> clazz) throws InstantiationException;
+}
diff --git a/src/org/easymock/internal/ILegacyMatcherMethods.java b/src/org/easymock/internal/ILegacyMatcherMethods.java
deleted file mode 100644
index 2f6426a..0000000
--- a/src/org/easymock/internal/ILegacyMatcherMethods.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.lang.reflect.Method;
-
-public interface ILegacyMatcherMethods {
-
-    @SuppressWarnings("deprecation")
-    void setDefaultMatcher(org.easymock.ArgumentsMatcher matcher);
-
-    @SuppressWarnings("deprecation")
-    void setMatcher(Method method, org.easymock.ArgumentsMatcher matcher);
-}
\ No newline at end of file
diff --git a/src/org/easymock/internal/ILegacyMethods.java b/src/org/easymock/internal/ILegacyMethods.java
deleted file mode 100644
index cf7bc9b..0000000
--- a/src/org/easymock/internal/ILegacyMethods.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-public interface ILegacyMethods extends ILegacyMatcherMethods {
-    void setDefaultReturnValue(Object value);
-
-    void setDefaultThrowable(Throwable throwable);
-
-    void setDefaultVoidCallable();
-}
diff --git a/src/org/easymock/internal/IMocksBehavior.java b/src/org/easymock/internal/IMocksBehavior.java
index 1d40ae9..1c41713 100644
--- a/src/org/easymock/internal/IMocksBehavior.java
+++ b/src/org/easymock/internal/IMocksBehavior.java
@@ -1,27 +1,43 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-public interface IMocksBehavior extends ILegacyMatcherMethods {
-
-    // record
-    void addExpected(ExpectedInvocation expected, Result result, Range count);
-
-    void addStub(ExpectedInvocation expected, Result result);
-
-    void checkOrder(boolean value);
-
-    // replay
-    Result addActual(Invocation invocation);
-    
-    void makeThreadSafe(boolean isThreadSafe);
-
-    boolean isThreadSafe();
-    
-    void checkCurrentThreadSameAsLastThread();
-    
-    // verify
-    void verify();
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public interface IMocksBehavior {
+
+    // record
+    void addExpected(ExpectedInvocation expected, Result result, Range count);
+
+    void addStub(ExpectedInvocation expected, Result result);
+
+    void checkOrder(boolean value);
+
+    void makeThreadSafe(boolean isThreadSafe);
+
+    void shouldBeUsedInOneThread(boolean shouldBeUsedInOneThread);
+
+    // replay
+    Result addActual(Invocation invocation);
+
+    boolean isThreadSafe();
+
+    void checkThreadSafety();
+
+    // verify
+    void verify();
+}
diff --git a/src/org/easymock/internal/IMocksControlState.java b/src/org/easymock/internal/IMocksControlState.java
index 6e6540c..f053945 100644
--- a/src/org/easymock/internal/IMocksControlState.java
+++ b/src/org/easymock/internal/IMocksControlState.java
@@ -1,38 +1,58 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import org.easymock.IAnswer;
-
-public interface IMocksControlState extends ILegacyMethods {
-
-    Object invoke(Invocation invocation) throws Throwable;
-
-    void assertRecordState();
-
-    void andReturn(Object value);
-
-    void andThrow(Throwable throwable);
-
-    void andAnswer(IAnswer<?> answer);
-
-    void andStubReturn(Object value);
-
-    void andStubThrow(Throwable throwable);
-
-    void andStubAnswer(IAnswer<?> answer);
-
-    void asStub();
-
-    void times(Range range);
-
-    void checkOrder(boolean value);
-
-    void makeThreadSafe(boolean threadSafe);
-    
-    void replay();
-
-    void verify();
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import org.easymock.IAnswer;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public interface IMocksControlState {
+
+    Object invoke(Invocation invocation) throws Throwable;
+
+    void assertRecordState();
+
+    void andReturn(Object value);
+
+    void andThrow(Throwable throwable);
+
+    void andAnswer(IAnswer<?> answer);
+
+    void andDelegateTo(Object answer);
+
+    void andStubReturn(Object value);
+
+    void andStubThrow(Throwable throwable);
+
+    void andStubAnswer(IAnswer<?> answer);
+
+    void andStubDelegateTo(Object delegateTo);
+
+    void asStub();
+
+    void times(Range range);
+
+    void checkOrder(boolean value);
+
+    void makeThreadSafe(boolean threadSafe);
+
+    void checkIsUsedInOneThread(boolean shouldBeUsedInOneThread);
+
+    void replay();
+
+    void verify();
+}
diff --git a/src/org/easymock/internal/IProxyFactory.java b/src/org/easymock/internal/IProxyFactory.java
index 5729523..10bf09e 100644
--- a/src/org/easymock/internal/IProxyFactory.java
+++ b/src/org/easymock/internal/IProxyFactory.java
@@ -1,11 +1,47 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.lang.reflect.InvocationHandler;
-
-public interface IProxyFactory<T> {
-    T createProxy(Class<T> toMock, InvocationHandler handler);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import org.easymock.ConstructorArgs;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public interface IProxyFactory {
+
+    /**
+     * @param toMock the class to mock by the factory
+     * @param handler the handler that will be linked to the created proxy
+     * @param mockedMethods the subset of {@code toMock}'s methods to mock, or
+     *     null to mock all methods.
+     * @param constructorArgs the constructor arguments to use, or null to use
+     *     heuristics to choose a constructor.
+     * @return the newly created proxy
+     */
+    <T> T createProxy(Class<T> toMock, InvocationHandler handler, Method[] mockedMethods,
+            ConstructorArgs constructorArgs);
+
+    /**
+     * Returns the invocation handler for {@code mock};
+     *
+     * @param mock a mock instance previously returned by {@code createProxy}.
+     * @return the handler handling method calls for the {@code mock}
+     */
+    InvocationHandler getInvocationHandler(Object mock);
+}
diff --git a/src/org/easymock/internal/Invocation.java b/src/org/easymock/internal/Invocation.java
index ae4ddcc..af754af 100644
--- a/src/org/easymock/internal/Invocation.java
+++ b/src/org/easymock/internal/Invocation.java
@@ -1,168 +1,223 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import static java.lang.Character.*;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.lang.reflect.Method;
-
-import org.easymock.internal.matchers.ArrayEquals;
-
-public class Invocation implements Serializable {
-
-    private static final long serialVersionUID = -2836226970244118495L;
-
-    private final Object mock;
-
-    private transient Method method;
-
-    private final Object[] arguments;
-
-    public Invocation(Object mock, Method method, Object[] args) {
-        this.mock = mock;
-        this.method = method;
-        this.arguments = expandVarArgs(method.isVarArgs(), args);
-    }
-
-    private static Object[] expandVarArgs(final boolean isVarArgs,
-            final Object[] args) {
-        if (!isVarArgs || isVarArgs && args[args.length - 1] != null
-                && !args[args.length - 1].getClass().isArray()) {
-            return args == null ? new Object[0] : args;
-        }
-        Object[] varArgs = ArrayEquals.createObjectArray(args[args.length - 1]);
-        final int nonVarArgsCount = args.length - 1;
-        final int varArgsCount = varArgs.length;
-        Object[] newArgs = new Object[nonVarArgsCount + varArgsCount];
-        System.arraycopy(args, 0, newArgs, 0, nonVarArgsCount);
-        System.arraycopy(varArgs, 0, newArgs, nonVarArgsCount, varArgsCount);
-        return newArgs;
-    }
-
-    public Object getMock() {
-        return mock;
-    }
-
-    public Method getMethod() {
-        return method;
-    }
-
-    public Object[] getArguments() {
-        return arguments;
-    }
-
-    public boolean equals(Object o) {
-        if (o == null || !o.getClass().equals(this.getClass()))
-            return false;
-
-        Invocation other = (Invocation) o;
-
-        return this.mock.equals(other.mock) && this.method.equals(other.method)
-                && this.equalArguments(other.arguments);
-    }
-
-    public int hashCode() {
-        throw new UnsupportedOperationException("hashCode() is not implemented");
-    }
-
-    private boolean equalArguments(Object[] arguments) {
-        if (this.arguments.length != arguments.length) {
-            return false;
-        }
-        for (int i = 0; i < this.arguments.length; i++) {
-            Object myArgument = this.arguments[i];
-            Object otherArgument = arguments[i];
-
-            if (isPrimitiveParameter(i)) {
-                if (!myArgument.equals(otherArgument)) {
-                    return false;
-                }
-            } else {
-                if (myArgument != otherArgument) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    private boolean isPrimitiveParameter(int parameterPosition) {
-        Class<?>[] parameterTypes = method.getParameterTypes();
-        if (method.isVarArgs()) {
-            parameterPosition = Math.min(parameterPosition,
-                    parameterTypes.length - 1);
-        }
-        return parameterTypes[parameterPosition].isPrimitive();
-    }
-
-    @SuppressWarnings("deprecation")
-    public boolean matches(Invocation actual, org.easymock.ArgumentsMatcher matcher) {
-        return this.mock.equals(actual.mock)
-                && this.method.equals(actual.method)
-                && matcher.matches(this.arguments, actual.arguments);
-    }
-
-    @SuppressWarnings("deprecation")
-    public String toString(org.easymock.ArgumentsMatcher matcher) {
-        return getMockAndMethodName() + "(" + matcher.toString(arguments) + ")";
-    }
-
-    public String getMockAndMethodName() {
-        String mockName = mock.toString();
-        String methodName = method.getName();
-        if (toStringIsDefined(mock) && isJavaIdentifier(mockName)) {
-            return mockName + "." + methodName;
-        } else {
-            return methodName;
-        }
-    }
-
-    private boolean toStringIsDefined(Object o) {
-        try {
-            o.getClass().getDeclaredMethod("toString", (Class[]) null)
-                    .getModifiers();
-            return true;
-        } catch (SecurityException ignored) {
-            // ///CLOVER:OFF
-            return false;
-            // ///CLOVER:ON
-        } catch (NoSuchMethodException shouldNeverHappen) {
-            // ///CLOVER:OFF
-            throw new RuntimeException("The toString() method could not be found!");
-            // ///CLOVER:ON
-        }
-    }
-
-    public static boolean isJavaIdentifier(String mockName) {
-        if (mockName.length() == 0 || mockName.indexOf(' ') > -1
-                || !Character.isJavaIdentifierStart(mockName.charAt(0))) {
-            return false;
-        }
-        for (char c : mockName.substring(1).toCharArray()) {
-            if (!isJavaIdentifierPart(c)) {
-                return false;
-            }
-        }
-        return true;
-    }
-    
-    private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
-        stream.defaultReadObject();
-        try {
-            method = ((MethodSerializationWrapper) stream.readObject()).getMethod();
-        } catch (NoSuchMethodException e) {
-            // ///CLOVER:OFF
-            throw new IOException(e.toString());
-            // ///CLOVER:ON
-        }
-    }
-    
-    private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
-        stream.defaultWriteObject();
-        stream.writeObject(new MethodSerializationWrapper(method));
-    }    
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import static java.lang.Character.*;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.easymock.internal.matchers.Captures;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Invocation implements Serializable {
+
+    private static final long serialVersionUID = 1604995470419943411L;
+
+    private static final Object[] NO_ARGS = {};
+
+    private final Object mock;
+
+    private transient Method method;
+
+    private final Object[] arguments;
+
+    private final Collection<Captures<?>> currentCaptures = new ArrayList<Captures<?>>(0);
+
+    public Invocation(final Object mock, final Method method, final Object[] args) {
+        this.mock = mock;
+        this.method = method;
+        this.arguments = expandVarArgs(method.isVarArgs(), args);
+    }
+
+    private static Object[] expandVarArgs(final boolean isVarArgs, final Object[] args) {
+        if (!isVarArgs) {
+            return args == null ? NO_ARGS : args;
+        }
+        if (args[args.length - 1] == null) {
+            return args;
+        }
+        final Object[] varArgs = createObjectArray(args[args.length - 1]);
+        final int nonVarArgsCount = args.length - 1;
+        final int varArgsCount = varArgs.length;
+        final Object[] newArgs = new Object[nonVarArgsCount + varArgsCount];
+        System.arraycopy(args, 0, newArgs, 0, nonVarArgsCount);
+        System.arraycopy(varArgs, 0, newArgs, nonVarArgsCount, varArgsCount);
+        return newArgs;
+    }
+
+    private static Object[] createObjectArray(final Object array) {
+        if (array instanceof Object[]) {
+            return (Object[]) array;
+        }
+        final Object[] result = new Object[Array.getLength(array)];
+        for (int i = 0; i < Array.getLength(array); i++) {
+            result[i] = Array.get(array, i);
+        }
+        return result;
+    }
+
+    public Object getMock() {
+        return mock;
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+
+    public Object[] getArguments() {
+        return arguments;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (o == null || !o.getClass().equals(this.getClass())) {
+            return false;
+        }
+
+        final Invocation other = (Invocation) o;
+
+        return this.mock.equals(other.mock) && this.method.equals(other.method)
+                && this.equalArguments(other.arguments);
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("hashCode() is not implemented");
+    }
+
+    @Override
+    public String toString() {
+        return getMockAndMethodName() + "(" + ArgumentToString.argumentsToString(arguments) + ")";
+    }
+
+    private boolean equalArguments(final Object[] arguments) {
+        if (this.arguments.length != arguments.length) {
+            return false;
+        }
+        for (int i = 0; i < this.arguments.length; i++) {
+            final Object myArgument = this.arguments[i];
+            final Object otherArgument = arguments[i];
+
+            if (isPrimitiveParameter(i)) {
+                if (!myArgument.equals(otherArgument)) {
+                    return false;
+                }
+            } else {
+                if (myArgument != otherArgument) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean isPrimitiveParameter(int parameterPosition) {
+        final Class<?>[] parameterTypes = method.getParameterTypes();
+        if (method.isVarArgs()) {
+            parameterPosition = Math.min(parameterPosition, parameterTypes.length - 1);
+        }
+        return parameterTypes[parameterPosition].isPrimitive();
+    }
+
+    public String getMockAndMethodName() {
+        final String methodName = method.getName();
+        // This can occur when using PowerMock. They do something that causes the mock
+        // to not implement toString. So I start by making sure it is really my to String
+        // that I call... There's probably a better solution
+        if (!toStringIsDefined(mock)) {
+            return methodName;
+        }
+        final String mockName = mock.toString();
+        // Cheap trick to check if the name is the default "EasyMock for ..." or a name 
+        // provided when creating the mock
+        if (isJavaIdentifier(mockName)) {
+            return mockName + "." + methodName;
+        }
+
+        final Class<?> clazz = MocksControl.getMockedType(mock);
+        return clazz.getSimpleName() + "." + methodName;
+    }
+
+    public void addCapture(final Captures<Object> capture, final Object value) {
+        capture.setPotentialValue(value);
+        currentCaptures.add(capture);
+    }
+
+    public void validateCaptures() {
+        for (final Captures<?> c : currentCaptures) {
+            c.validateCapture();
+        }
+    }
+
+    public void clearCaptures() {
+        for (final Captures<?> c : currentCaptures) {
+            c.setPotentialValue(null);
+        }
+        currentCaptures.clear();
+    }
+
+    private boolean toStringIsDefined(final Object o) {
+        try {
+            o.getClass().getDeclaredMethod("toString", (Class[]) null).getModifiers();
+            return true;
+        } catch (final SecurityException ignored) {
+            // ///CLOVER:OFF
+            return false;
+            // ///CLOVER:ON
+        } catch (final NoSuchMethodException ignored) {
+            // ///CLOVER:OFF
+            return false;
+            // ///CLOVER:ON
+        }
+    }
+
+    public static boolean isJavaIdentifier(final String mockName) {
+        if (mockName.length() == 0 || mockName.indexOf(' ') > -1
+                || !Character.isJavaIdentifierStart(mockName.charAt(0))) {
+            return false;
+        }
+        for (final char c : mockName.substring(1).toCharArray()) {
+            if (!isJavaIdentifierPart(c)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void readObject(final java.io.ObjectInputStream stream) throws IOException,
+            ClassNotFoundException {
+        stream.defaultReadObject();
+        try {
+            method = ((MethodSerializationWrapper) stream.readObject()).getMethod();
+        } catch (final NoSuchMethodException e) {
+            // ///CLOVER:OFF
+            throw new IOException(e.toString());
+            // ///CLOVER:ON
+        }
+    }
+
+    private void writeObject(final java.io.ObjectOutputStream stream) throws IOException {
+        stream.defaultWriteObject();
+        stream.writeObject(new MethodSerializationWrapper(method));
+    }
+}
diff --git a/src/org/easymock/internal/JavaProxyFactory.java b/src/org/easymock/internal/JavaProxyFactory.java
index 4ff1126..255d6f8 100644
--- a/src/org/easymock/internal/JavaProxyFactory.java
+++ b/src/org/easymock/internal/JavaProxyFactory.java
@@ -1,16 +1,36 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-
-public class JavaProxyFactory<T> implements IProxyFactory<T> {
-    @SuppressWarnings("unchecked")
-    public T createProxy(Class<T> toMock, InvocationHandler handler) {
-        return (T) Proxy.newProxyInstance(toMock.getClassLoader(),
-                new Class[] { toMock }, handler);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import org.easymock.ConstructorArgs;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class JavaProxyFactory implements IProxyFactory {
+    @SuppressWarnings("unchecked")
+    public <T> T createProxy(Class<T> toMock, InvocationHandler handler,
+            Method[] mockedMethods, ConstructorArgs constructorArgs) {
+        return (T) Proxy.newProxyInstance(toMock.getClassLoader(), new Class[] { toMock }, handler);
+    }
+
+    public InvocationHandler getInvocationHandler(Object mock) {
+        return Proxy.getInvocationHandler(mock);
+    }
+}
diff --git a/src/org/easymock/internal/LastControl.java b/src/org/easymock/internal/LastControl.java
index c74d8f7..960932d 100644
--- a/src/org/easymock/internal/LastControl.java
+++ b/src/org/easymock/internal/LastControl.java
@@ -1,110 +1,135 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.util.*;
-
-import org.easymock.IArgumentMatcher;
-import org.easymock.internal.matchers.And;
-import org.easymock.internal.matchers.Not;
-import org.easymock.internal.matchers.Or;
-
-public class LastControl {
-    private static final ThreadLocal<MocksControl> threadToControl = new ThreadLocal<MocksControl>();
-
-    private static final ThreadLocal<Stack<Object[]>> threadToCurrentArguments = new ThreadLocal<Stack<Object[]>>();
-
-    private static final ThreadLocal<Stack<IArgumentMatcher>> threadToArgumentMatcherStack = new ThreadLocal<Stack<IArgumentMatcher>>();
-
-    public static synchronized void reportLastControl(MocksControl control) {
-        if (control != null) {
-            threadToControl.set(control);
-        } else {
-            threadToControl.remove();
-        }
-    }
-
-    public static synchronized MocksControl lastControl() {
-        return threadToControl.get();
-    }
-
-    public static synchronized void reportMatcher(IArgumentMatcher matcher) {
-        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
-        if (stack == null) {
-            stack = new Stack<IArgumentMatcher>();
-            threadToArgumentMatcherStack.set(stack);
-        }
-        stack.push(matcher);
-    }
-
-    public static synchronized List<IArgumentMatcher> pullMatchers() {
-        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
-        if (stack == null) {
-            return null;
-        }
-        threadToArgumentMatcherStack.remove();
-        return new ArrayList<IArgumentMatcher>(stack);
-    }
-
-    public static synchronized void reportAnd(int count) {
-        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
-        assertState(stack != null, "no matchers found.");
-        stack.push(new And(popLastArgumentMatchers(count)));
-    }
-
-    public static synchronized void reportNot() {
-        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
-        assertState(stack != null, "no matchers found.");
-        stack.push(new Not(popLastArgumentMatchers(1).get(0)));
-    }
-
-    private static List<IArgumentMatcher> popLastArgumentMatchers(int count) {
-        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
-        assertState(stack != null, "no matchers found.");
-        assertState(stack.size() >= count, "" + count + " matchers expected, "
-                + stack.size() + " recorded.");
-        List<IArgumentMatcher> result = new LinkedList<IArgumentMatcher>();
-        result.addAll(stack.subList(stack.size() - count, stack.size()));
-        for (int i = 0; i < count; i++) {
-            stack.pop();
-        }
-        return result;
-    }
-
-    private static void assertState(boolean toAssert, String message) {
-        if (!toAssert) {
-            threadToArgumentMatcherStack.remove();
-            throw new IllegalStateException(message);
-        }
-    }
-
-    public static void reportOr(int count) {
-        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
-        assertState(stack != null, "no matchers found.");
-        stack.push(new Or(popLastArgumentMatchers(count)));
-    }
-
-    public static Object[] getCurrentArguments() {
-        Stack<Object[]> stack = threadToCurrentArguments.get();
-        if (stack == null || stack.empty()) {
-            return null;
-        }
-        return stack.lastElement();
-    }
-
-    public static void pushCurrentArguments(Object[] args) {
-        Stack<Object[]> stack = threadToCurrentArguments.get();
-        if (stack == null) {
-            stack = new Stack<Object[]>();
-            threadToCurrentArguments.set(stack);
-        }
-        stack.push(args);
-    }
-
-    public static void popCurrentArguments() {
-        Stack<Object[]> stack = threadToCurrentArguments.get();
-        stack.pop();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+import org.easymock.IArgumentMatcher;
+import org.easymock.internal.matchers.And;
+import org.easymock.internal.matchers.Not;
+import org.easymock.internal.matchers.Or;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public final class LastControl {
+
+    private static final String NO_MATCHERS_FOUND = "no matchers found.";
+
+    private static final ThreadLocal<MocksControl> threadToControl = new ThreadLocal<MocksControl>();
+
+    private static final ThreadLocal<Stack<Invocation>> threadToCurrentInvocation = new ThreadLocal<Stack<Invocation>>();
+
+    private static final ThreadLocal<Stack<IArgumentMatcher>> threadToArgumentMatcherStack = new ThreadLocal<Stack<IArgumentMatcher>>();
+
+    // ///CLOVER:OFF
+    private LastControl() {
+    }
+
+    // ///CLOVER:ON
+
+    public static void reportLastControl(final MocksControl control) {
+        if (control != null) {
+            threadToControl.set(control);
+        } else {
+            threadToControl.remove();
+        }
+    }
+
+    public static MocksControl lastControl() {
+        return threadToControl.get();
+    }
+
+    public static void reportMatcher(final IArgumentMatcher matcher) {
+        Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
+        if (stack == null) {
+            stack = new Stack<IArgumentMatcher>();
+            threadToArgumentMatcherStack.set(stack);
+        }
+        stack.push(matcher);
+    }
+
+    public static List<IArgumentMatcher> pullMatchers() {
+        final Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
+        if (stack == null) {
+            return null;
+        }
+        threadToArgumentMatcherStack.remove();
+        return new ArrayList<IArgumentMatcher>(stack);
+    }
+
+    public static void reportAnd(final int count) {
+        final Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
+        assertState(stack != null, NO_MATCHERS_FOUND);
+        stack.push(new And(popLastArgumentMatchers(count)));
+    }
+
+    public static void reportNot() {
+        final Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
+        assertState(stack != null, NO_MATCHERS_FOUND);
+        stack.push(new Not(popLastArgumentMatchers(1).get(0)));
+    }
+
+    private static List<IArgumentMatcher> popLastArgumentMatchers(final int count) {
+        final Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
+        assertState(stack != null, NO_MATCHERS_FOUND);
+        assertState(stack.size() >= count, "" + count + " matchers expected, " + stack.size() + " recorded.");
+        final List<IArgumentMatcher> result = new LinkedList<IArgumentMatcher>();
+        result.addAll(stack.subList(stack.size() - count, stack.size()));
+        for (int i = 0; i < count; i++) {
+            stack.pop();
+        }
+        return result;
+    }
+
+    private static void assertState(final boolean toAssert, final String message) {
+        if (!toAssert) {
+            threadToArgumentMatcherStack.remove();
+            throw new IllegalStateException(message);
+        }
+    }
+
+    public static void reportOr(final int count) {
+        final Stack<IArgumentMatcher> stack = threadToArgumentMatcherStack.get();
+        assertState(stack != null, NO_MATCHERS_FOUND);
+        stack.push(new Or(popLastArgumentMatchers(count)));
+    }
+
+    public static Invocation getCurrentInvocation() {
+        final Stack<Invocation> stack = threadToCurrentInvocation.get();
+        if (stack == null || stack.empty()) {
+            return null;
+        }
+        return stack.lastElement();
+    }
+
+    public static void pushCurrentInvocation(final Invocation invocation) {
+        Stack<Invocation> stack = threadToCurrentInvocation.get();
+        if (stack == null) {
+            stack = new Stack<Invocation>();
+            threadToCurrentInvocation.set(stack);
+        }
+        stack.push(invocation);
+    }
+
+    public static void popCurrentInvocation() {
+        final Stack<Invocation> stack = threadToCurrentInvocation.get();
+        stack.pop();
+    }
+}
diff --git a/src/org/easymock/internal/LegacyMatcherProvider.java b/src/org/easymock/internal/LegacyMatcherProvider.java
deleted file mode 100644
index 662b2a2..0000000
--- a/src/org/easymock/internal/LegacyMatcherProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.easymock.ArgumentsMatcher;
-import org.easymock.MockControl;
-
- at SuppressWarnings("deprecation")
-public class LegacyMatcherProvider {
-
-    private ArgumentsMatcher defaultMatcher;
-
-    private boolean defaultMatcherSet;
-
-    private Map<Method, ArgumentsMatcher> matchers = new HashMap<Method, ArgumentsMatcher>();
-
-    public ArgumentsMatcher getMatcher(Method method) {
-        if (!matchers.containsKey(method)) {
-            if (!defaultMatcherSet) {
-                setDefaultMatcher(MockControl.EQUALS_MATCHER);
-            }
-            matchers.put(method, defaultMatcher);
-        }
-        return matchers.get(method);
-    }
-
-    
-    public void setDefaultMatcher(ArgumentsMatcher matcher) {
-        if (defaultMatcherSet) {
-            throw new RuntimeExceptionWrapper(
-                    new IllegalStateException(
-                            "default matcher can only be set once directly after creation of the MockControl"));
-        }
-        defaultMatcher = matcher;
-        defaultMatcherSet = true;
-    }
-
-    public void setMatcher(Method method, ArgumentsMatcher matcher) {
-        if (matchers.containsKey(method) && matchers.get(method) != matcher) {
-            throw new RuntimeExceptionWrapper(new IllegalStateException(
-                    "for method "
-                            + method.getName()
-                            + "("
-                            + (method.getParameterTypes().length == 0 ? ""
-                                    : "...")
-                            + "), a matcher has already been set"));
-        }
-        matchers.put(method, matcher);
-    }
-}
diff --git a/src/org/easymock/internal/MethodSerializationWrapper.java b/src/org/easymock/internal/MethodSerializationWrapper.java
index 2a2c153..853751a 100644
--- a/src/org/easymock/internal/MethodSerializationWrapper.java
+++ b/src/org/easymock/internal/MethodSerializationWrapper.java
@@ -1,66 +1,81 @@
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-
-public class MethodSerializationWrapper implements Serializable {
-
-    private static final long serialVersionUID = 1775475200823842126L;
-
-    private static final Map<String, Class<?>> primitiveTypes = new HashMap<String, Class<?>>(
-            10);
-
-    static {
-        primitiveTypes.put(Boolean.TYPE.getName(), Boolean.TYPE);
-        primitiveTypes.put(Byte.TYPE.getName(), Byte.TYPE);
-        primitiveTypes.put(Short.TYPE.getName(), Short.TYPE);
-        primitiveTypes.put(Character.TYPE.getName(), Character.TYPE);
-        primitiveTypes.put(Integer.TYPE.getName(), Integer.TYPE);
-        primitiveTypes.put(Long.TYPE.getName(), Long.TYPE);
-        primitiveTypes.put(Float.TYPE.getName(), Float.TYPE);
-        primitiveTypes.put(Double.TYPE.getName(), Double.TYPE);
-    }
-
-    private String className;
-
-    private String methodName;
-
-    private String[] parameterTypeNames;
-
-    public MethodSerializationWrapper(Method m) {
-        className = m.getDeclaringClass().getName();
-        methodName = m.getName();
-
-        Class<?>[] parameterTypes = m.getParameterTypes();
-
-        parameterTypeNames = new String[parameterTypes.length];
-
-        for (int i = 0; i < parameterTypes.length; i++) {
-            parameterTypeNames[i] = parameterTypes[i].getName();
-        }
-    }
-
-    public Method getMethod() throws ClassNotFoundException,
-            NoSuchMethodException {
-        Class<?> clazz = Class.forName(className, true, Thread.currentThread()
-                .getContextClassLoader());
-
-        Class<?>[] parameterTypes = new Class[parameterTypeNames.length];
-
-        for (int i = 0; i < parameterTypeNames.length; i++) {
-            Class<?> primitiveType = primitiveTypes.get(parameterTypeNames[i]);
-            if (primitiveType != null) {
-                parameterTypes[i] = primitiveType;
-            } else {
-                parameterTypes[i] = Class.forName(parameterTypeNames[i], true,
-                        Thread.currentThread().getContextClassLoader());
-            }
-        }
-
-        Method m = clazz.getMethod(methodName, parameterTypes);
-
-        return m;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Henri Tremblay
+ */
+public class MethodSerializationWrapper implements Serializable {
+
+    private static final long serialVersionUID = 1775475200823842126L;
+
+    private static final Map<String, Class<?>> primitiveTypes = new HashMap<String, Class<?>>(10);
+
+    static {
+        primitiveTypes.put(Boolean.TYPE.getName(), Boolean.TYPE);
+        primitiveTypes.put(Byte.TYPE.getName(), Byte.TYPE);
+        primitiveTypes.put(Short.TYPE.getName(), Short.TYPE);
+        primitiveTypes.put(Character.TYPE.getName(), Character.TYPE);
+        primitiveTypes.put(Integer.TYPE.getName(), Integer.TYPE);
+        primitiveTypes.put(Long.TYPE.getName(), Long.TYPE);
+        primitiveTypes.put(Float.TYPE.getName(), Float.TYPE);
+        primitiveTypes.put(Double.TYPE.getName(), Double.TYPE);
+    }
+
+    private final String className;
+
+    private final String methodName;
+
+    private final String[] parameterTypeNames;
+
+    public MethodSerializationWrapper(final Method m) {
+        className = m.getDeclaringClass().getName();
+        methodName = m.getName();
+
+        final Class<?>[] parameterTypes = m.getParameterTypes();
+
+        parameterTypeNames = new String[parameterTypes.length];
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            parameterTypeNames[i] = parameterTypes[i].getName();
+        }
+    }
+
+    public Method getMethod() throws ClassNotFoundException, NoSuchMethodException {
+        final Class<?> clazz = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
+
+        final Class<?>[] parameterTypes = new Class[parameterTypeNames.length];
+
+        for (int i = 0; i < parameterTypeNames.length; i++) {
+            final Class<?> primitiveType = primitiveTypes.get(parameterTypeNames[i]);
+            if (primitiveType != null) {
+                parameterTypes[i] = primitiveType;
+            } else {
+                parameterTypes[i] = Class.forName(parameterTypeNames[i], true, Thread.currentThread()
+                        .getContextClassLoader());
+            }
+        }
+
+        final Method m = clazz.getDeclaredMethod(methodName, parameterTypes);
+
+        return m;
+    }
+}
diff --git a/src/org/easymock/internal/MockBuilder.java b/src/org/easymock/internal/MockBuilder.java
new file mode 100644
index 0000000..1fb3d52
--- /dev/null
+++ b/src/org/easymock/internal/MockBuilder.java
@@ -0,0 +1,239 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.easymock.*;
+
+/**
+ * Default implementation of IMockBuilder.
+ * <p>
+ * <i>The original idea and part of the code where contributed by Rodrigo
+ * Damazio and Bruno Fonseca at <a href="http://www.google.com">Google</a></i>
+ * 
+ * @param <T>
+ *            type of the mock created
+ * 
+ * @author Henri Tremblay
+ */
+public class MockBuilder<T> implements IMockBuilder<T> {
+
+    private final Class<T> toMock;
+
+    private Set<Method> mockedMethods;
+
+    private Constructor<T> constructor;
+
+    private ConstructorArgs constructorArgs;
+
+    private final EasyMockSupport support;
+
+    public MockBuilder(final Class<T> toMock) {
+        this(toMock, null);
+    }
+
+    /**
+     * Used by EasyMockSupport to allow the mock registration in the list of
+     * controls
+     * 
+     * @param toMock
+     *            The class of the mock to create
+     * @param support
+     *            The EasyMockSupport used to create mocks. Null if none
+     */
+    public MockBuilder(final Class<T> toMock, final EasyMockSupport support) {
+        this.toMock = toMock;
+        this.support = support;
+    }
+
+    public IMockBuilder<T> addMockedMethod(final Method method) {
+        if (Modifier.isFinal(method.getModifiers())) {
+            throw new IllegalArgumentException("Final methods can't be mocked");
+        }
+        if (mockedMethods == null) {
+            mockedMethods = new HashSet<Method>();
+        }
+        mockedMethods.add(method);
+        return this;
+    }
+
+    public IMockBuilder<T> addMockedMethod(final String methodName) {
+        final Method m = ReflectionUtils.findMethod(toMock, methodName);
+        if (m == null) {
+            throw new IllegalArgumentException("Method not found (or private): " + methodName);
+        }
+        addMockedMethod(m);
+        return this;
+    }
+
+    public IMockBuilder<T> addMockedMethod(final String methodName, final Class<?>... parameterTypes) {
+        final Method m = ReflectionUtils.findMethod(toMock, methodName, parameterTypes);
+        if (m == null) {
+            throw new IllegalArgumentException("Method not found (or private): " + methodName);
+        }
+        addMockedMethod(m);
+        return this;
+    }
+
+    public IMockBuilder<T> addMockedMethods(final String... methodNames) {
+        for (final String methodName : methodNames) {
+            addMockedMethod(methodName);
+        }
+        return this;
+    }
+
+    public IMockBuilder<T> addMockedMethods(final Method... methods) {
+        for (final Method method : methods) {
+            addMockedMethod(method);
+        }
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public IMockBuilder<T> withConstructor(final Constructor<?> constructor) {
+        checkConstructorNotInitialized();
+        this.constructor = (Constructor<T>) constructor;
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public IMockBuilder<T> withConstructor(final ConstructorArgs constructorArgs) {
+        checkConstructorNotInitialized();
+        this.constructor = (Constructor<T>) constructorArgs.getConstructor();
+        this.constructorArgs = constructorArgs;
+        return this;
+    }
+
+    public IMockBuilder<T> withConstructor() {
+        checkConstructorNotInitialized();
+        try {
+            constructor = ReflectionUtils.getConstructor(toMock);
+        } catch (final NoSuchMethodException e) {
+            throw new IllegalArgumentException("No empty constructor can be found", e);
+        }
+        constructorArgs = new ConstructorArgs(constructor);
+        return this;
+    }
+
+    public IMockBuilder<T> withConstructor(final Object... initArgs) {
+        checkConstructorNotInitialized();
+        try {
+            constructor = ReflectionUtils.getConstructor(toMock, initArgs);
+        } catch (final NoSuchMethodException e) {
+            throw new IllegalArgumentException("No constructor matching arguments can be found", e);
+        }
+        constructorArgs = new ConstructorArgs(constructor, initArgs);
+        return this;
+    }
+
+    public IMockBuilder<T> withConstructor(final Class<?>... argTypes) {
+        checkConstructorNotInitialized();
+
+        try {
+            constructor = toMock.getDeclaredConstructor(argTypes);
+        } catch (final NoSuchMethodException e) {
+            throw new IllegalArgumentException("No constructor matching arguments can be found", e);
+        }
+        return this;
+    }
+
+    public IMockBuilder<T> withArgs(final Object... initArgs) {
+        if (constructor == null) {
+            throw new IllegalStateException(
+                    "Trying to define constructor arguments without first setting their type.");
+        }
+        if (constructorArgs != null) {
+            throw new IllegalStateException("Trying to define the constructor arguments more than once.");
+        }
+
+        constructorArgs = new ConstructorArgs(constructor, initArgs);
+        return this;
+    }
+
+    public T createMock(final MockType type) {
+        final IMocksControl control = (support == null ? EasyMock.createControl(type) : support
+                .createControl(type));
+        return createMock(null, control);
+    }
+
+    public T createMock(final String name, final MockType type) {
+        final IMocksControl control = (support == null ? EasyMock.createControl(type) : support
+                .createControl(type));
+        return createMock(name, control);
+    }
+
+    public T createMock(final IMocksControl control) {
+        return createMock(null, control);
+    }
+
+    public T createMock() {
+        return createMock((String) null);
+    }
+
+    public T createNiceMock() {
+        return createNiceMock(null);
+    }
+
+    public T createStrictMock() {
+        return createStrictMock(null);
+    }
+
+    @SuppressWarnings("deprecation")
+    public T createMock(final String name, final IMocksControl control) {
+        final Method[] mockedMethodArray = (mockedMethods == null ? new Method[0] : mockedMethods
+                .toArray(new Method[mockedMethods.size()]));
+
+        // Create a mock with no default {@code withConstructor} was not called.
+        if (constructor == null) {
+            return control.createMock(name, toMock, mockedMethodArray);
+        }
+
+        // If the constructor is defined, so must be its arguments
+        if (constructorArgs == null) {
+            throw new IllegalStateException("Picked a constructor but didn't pass arguments to it");
+        }
+
+        return control.createMock(name, toMock, constructorArgs, mockedMethodArray);
+    }
+
+    public T createMock(final String name) {
+        final IMocksControl control = (support == null ? EasyMock.createControl() : support.createControl());
+        return createMock(name, control);
+    }
+
+    public T createNiceMock(final String name) {
+        final IMocksControl control = (support == null ? EasyMock.createNiceControl() : support
+                .createNiceControl());
+        return createMock(name, control);
+    }
+
+    public T createStrictMock(final String name) {
+        final IMocksControl control = (support == null ? EasyMock.createStrictControl() : support
+                .createStrictControl());
+        return createMock(name, control);
+    }
+
+    private void checkConstructorNotInitialized() {
+        if (constructor != null) {
+            throw new IllegalStateException("Trying to define the constructor call more than once.");
+        }
+    }
+}
diff --git a/src/org/easymock/internal/MockInvocationHandler.java b/src/org/easymock/internal/MockInvocationHandler.java
index 60ade89..3355d37 100644
--- a/src/org/easymock/internal/MockInvocationHandler.java
+++ b/src/org/easymock/internal/MockInvocationHandler.java
@@ -1,41 +1,54 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-
-public final class MockInvocationHandler implements InvocationHandler, Serializable {
-
-    private static final long serialVersionUID = -7799769066534714634L;
-    
-    private final MocksControl control;
-
-    public MockInvocationHandler(MocksControl control) {
-        this.control = control;
-    }
-
-    public Object invoke(Object proxy, Method method, Object[] args)
-            throws Throwable {
-        try {
-            if (control.getState() instanceof RecordState) {
-                LastControl.reportLastControl(control);
-            }
-            return control.getState().invoke(
-                    new Invocation(proxy, method, args));
-        } catch (RuntimeExceptionWrapper e) {
-            throw e.getRuntimeException().fillInStackTrace();
-        } catch (AssertionErrorWrapper e) {
-            throw e.getAssertionError().fillInStackTrace();
-        } catch (ThrowableWrapper t) {
-            throw t.getThrowable().fillInStackTrace();
-        }
-    }
-
-    public MocksControl getControl() {
-        return control;
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public final class MockInvocationHandler implements InvocationHandler, Serializable {
+
+    private static final long serialVersionUID = -7799769066534714634L;
+
+    private final MocksControl control;
+
+    public MockInvocationHandler(final MocksControl control) {
+        this.control = control;
+    }
+
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        try {
+            if (control.getState() instanceof RecordState) {
+                LastControl.reportLastControl(control);
+            }
+            return control.getState().invoke(new Invocation(proxy, method, args));
+        } catch (final RuntimeExceptionWrapper e) {
+            throw e.getRuntimeException().fillInStackTrace();
+        } catch (final AssertionErrorWrapper e) {
+            throw e.getAssertionError().fillInStackTrace();
+        } catch (final ThrowableWrapper t) {
+            throw t.getThrowable().fillInStackTrace();
+        }
+        // then let all unwrapped exceptions pass unmodified
+    }
+
+    public MocksControl getControl() {
+        return control;
+    }
 }
\ No newline at end of file
diff --git a/src/org/easymock/internal/MocksBehavior.java b/src/org/easymock/internal/MocksBehavior.java
index 706d74e..f8a9a32 100644
--- a/src/org/easymock/internal/MocksBehavior.java
+++ b/src/org/easymock/internal/MocksBehavior.java
@@ -1,162 +1,204 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MocksBehavior implements IMocksBehavior, Serializable {
-
-    private static final long serialVersionUID = 3265727009370529027L;
-
-    private final List<UnorderedBehavior> behaviorLists = new ArrayList<UnorderedBehavior>();
-
-    private List<ExpectedInvocationAndResult> stubResults = new ArrayList<ExpectedInvocationAndResult>();
-
-    private final boolean nice;
-
-    private boolean checkOrder;
-
-    private boolean isThreadSafe;
-
-    private int position = 0;
-
-    private transient volatile Thread lastThread;
-
-    public MocksBehavior(boolean nice) {
-        this.nice = nice;
-    }
-
-    public final void addStub(ExpectedInvocation expected, Result result) {
-        stubResults.add(new ExpectedInvocationAndResult(expected, result));
-    }
-
-    public void addExpected(ExpectedInvocation expected, Result result,
-            Range count) {
-        if (legacyMatcherProvider != null) {
-            expected = expected.withMatcher(legacyMatcherProvider
-                    .getMatcher(expected.getMethod()));
-        }
-        addBehaviorListIfNecessary(expected);
-        lastBehaviorList().addExpected(expected, result, count);
-    }
-
-    private final Result getStubResult(Invocation actual) {
-        for (ExpectedInvocationAndResult each : stubResults) {
-            if (each.getExpectedInvocation().matches(actual)) {
-                return each.getResult();
-            }
-        }
-        return null;
-    }
-
-    private void addBehaviorListIfNecessary(ExpectedInvocation expected) {
-        if (behaviorLists.isEmpty()
-                || !lastBehaviorList().allowsExpectedInvocation(expected,
-                        checkOrder)) {
-            behaviorLists.add(new UnorderedBehavior(checkOrder));
-        }
-    }
-
-    private UnorderedBehavior lastBehaviorList() {
-        return behaviorLists.get(behaviorLists.size() - 1);
-    }
-
-    @SuppressWarnings("deprecation")
-    public final Result addActual(Invocation actual) {
-        int tempPosition = position;
-        String errorMessage = "";
-        while (position < behaviorLists.size()) {
-            Result result = behaviorLists.get(position).addActual(actual);
-            if (result != null) {
-                return result;
-            }
-            errorMessage += behaviorLists.get(position).toString(actual);
-            if (!behaviorLists.get(position).verify()) {
-                break;
-            }
-            position++;
-        }
-        Result stubOrNice = getStubResult(actual);
-        if (stubOrNice == null && nice) {
-            stubOrNice = Result.createReturnResult(RecordState
-                    .emptyReturnValueFor(actual.getMethod().getReturnType()));
-        }
-
-        // Do not move the cursor in case of stub, nice or error
-        position = tempPosition;
-
-        if (stubOrNice != null) {
-            return stubOrNice;
-        }
-        throw new AssertionErrorWrapper(
-                new AssertionError(
-                        "\n  Unexpected method call "
-                                + actual
-                                        .toString(org.easymock.MockControl.EQUALS_MATCHER)
-                                + ":" + errorMessage.toString()));
-    }
-
-    public void verify() {
-        boolean verified = true;
-        StringBuffer errorMessage = new StringBuffer();
-
-        for (UnorderedBehavior behaviorList : behaviorLists.subList(position,
-                behaviorLists.size())) {
-            errorMessage.append(behaviorList.toString());
-            if (!behaviorList.verify()) {
-                verified = false;
-            }
-        }
-        if (verified) {
-            return;
-        }
-
-        throw new AssertionErrorWrapper(new AssertionError(
-                "\n  Expectation failure on verify:" + errorMessage.toString()));
-    }
-
-    public void checkOrder(boolean value) {
-        this.checkOrder = value;
-    }
-
-    public void makeThreadSafe(boolean isThreadSafe) {
-        this.isThreadSafe = isThreadSafe;
-    }
-
-    public boolean isThreadSafe() {
-        return this.isThreadSafe;
-    }
-
-    public void checkCurrentThreadSameAsLastThread() {
-        if (lastThread == null) {
-            lastThread = Thread.currentThread();
-        } else if(lastThread != Thread.currentThread()) {
-            throw new AssertionErrorWrapper(new AssertionError(
-                    "\n  Un-thread-safe mock called from multiple threads"));
-        }
-    }
-
-    private LegacyMatcherProvider legacyMatcherProvider;
-
-    public LegacyMatcherProvider getLegacyMatcherProvider() {
-        if (legacyMatcherProvider == null) {
-            legacyMatcherProvider = new LegacyMatcherProvider();
-        }
-        return legacyMatcherProvider;
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setDefaultMatcher(org.easymock.ArgumentsMatcher matcher) {
-        getLegacyMatcherProvider().setDefaultMatcher(matcher);
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setMatcher(Method method, org.easymock.ArgumentsMatcher matcher) {
-        getLegacyMatcherProvider().setMatcher(method, matcher);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class MocksBehavior implements IMocksBehavior, Serializable {
+
+    private static final long serialVersionUID = 3265727009370529027L;
+
+    private final List<UnorderedBehavior> behaviorLists = new ArrayList<UnorderedBehavior>();
+
+    private final List<ExpectedInvocationAndResult> stubResults = new ArrayList<ExpectedInvocationAndResult>();
+
+    private final boolean nice;
+
+    private boolean checkOrder;
+
+    private boolean isThreadSafe;
+
+    private boolean shouldBeUsedInOneThread;
+
+    private int position = 0;
+
+    private transient volatile Thread lastThread;
+
+    public MocksBehavior(final boolean nice) {
+        this.nice = nice;
+        this.isThreadSafe = !Boolean.valueOf(EasyMockProperties.getInstance().getProperty(
+                EasyMock.NOT_THREAD_SAFE_BY_DEFAULT));
+        this.shouldBeUsedInOneThread = Boolean.valueOf(EasyMockProperties.getInstance().getProperty(
+                EasyMock.ENABLE_THREAD_SAFETY_CHECK_BY_DEFAULT));
+    }
+
+    public final void addStub(final ExpectedInvocation expected, final Result result) {
+        stubResults.add(new ExpectedInvocationAndResult(expected, result));
+    }
+
+    public void addExpected(final ExpectedInvocation expected, final Result result, final Range count) {
+        addBehaviorListIfNecessary(expected);
+        lastBehaviorList().addExpected(expected, result, count);
+    }
+
+    private Result getStubResult(final Invocation actual) {
+        for (final ExpectedInvocationAndResult each : stubResults) {
+            if (each.getExpectedInvocation().matches(actual)) {
+                return each.getResult();
+            }
+        }
+        return null;
+    }
+
+    private void addBehaviorListIfNecessary(final ExpectedInvocation expected) {
+        if (behaviorLists.isEmpty() || !lastBehaviorList().allowsExpectedInvocation(expected, checkOrder)) {
+            behaviorLists.add(new UnorderedBehavior(checkOrder));
+        }
+    }
+
+    private UnorderedBehavior lastBehaviorList() {
+        return behaviorLists.get(behaviorLists.size() - 1);
+    }
+
+    public final Result addActual(final Invocation actual) {
+        final int initialPosition = position;
+
+        while (position < behaviorLists.size()) {
+            final Result result = behaviorLists.get(position).addActual(actual);
+            if (result != null) {
+                return result;
+            }
+            if (!behaviorLists.get(position).verify()) {
+                break;
+            }
+            position++;
+        }
+        Result stubOrNice = getStubResult(actual);
+        if (stubOrNice == null && nice) {
+            stubOrNice = Result.createReturnResult(RecordState.emptyReturnValueFor(actual.getMethod()
+                    .getReturnType()));
+        }
+
+        int endPosition = position;
+
+        // Do not move the cursor in case of stub, nice or error
+        position = initialPosition;
+
+        if (stubOrNice != null) {
+            actual.validateCaptures();
+            actual.clearCaptures();
+            return stubOrNice;
+        }
+
+        // Case where the loop was exited at the end of the behaviorLists
+        if (endPosition == behaviorLists.size()) {
+            endPosition--;
+        }
+
+        // Loop all around the behaviors left to generate the message
+        final StringBuilder errorMessage = new StringBuilder(70 * (endPosition - initialPosition + 1)); // rough approximation of the length
+        errorMessage.append("\n  Unexpected method call ").append(actual.toString());
+
+        final List<ErrorMessage> messages = new ArrayList<ErrorMessage>();
+
+        int matches = 0;
+
+        // First find how many match we have
+        for (int i = initialPosition; i <= endPosition; i++) {
+            final List<ErrorMessage> thisListMessages = behaviorLists.get(i).getMessages(actual);
+            messages.addAll(thisListMessages);
+            for (final ErrorMessage m : thisListMessages) {
+                if (m.isMatching()) {
+                    matches++;
+                }
+            }
+        }
+
+        if (matches > 1) {
+            errorMessage.append(". Possible matches are marked with (+1):");
+        } else {
+            errorMessage.append(":");
+        }
+
+        for (final ErrorMessage m : messages) {
+            m.appendTo(errorMessage, matches);
+        }
+
+        // And finally throw the error
+        throw new AssertionErrorWrapper(new AssertionError(errorMessage));
+    }
+
+    public void verify() {
+        boolean verified = true;
+
+        for (final UnorderedBehavior behaviorList : behaviorLists.subList(position, behaviorLists.size())) {
+            if (!behaviorList.verify()) {
+                verified = false;
+                break;
+            }
+        }
+        if (verified) {
+            return;
+        }
+
+        final StringBuilder errorMessage = new StringBuilder(70 * (behaviorLists.size() - position + 1));
+
+        errorMessage.append("\n  Expectation failure on verify:");
+        for (final UnorderedBehavior behaviorList : behaviorLists.subList(position, behaviorLists.size())) {
+            for (final ErrorMessage m : behaviorList.getMessages(null)) {
+                m.appendTo(errorMessage, 0);
+            }
+        }
+
+        throw new AssertionErrorWrapper(new AssertionError(errorMessage.toString()));
+    }
+
+    public void checkOrder(final boolean value) {
+        this.checkOrder = value;
+    }
+
+    public void makeThreadSafe(final boolean isThreadSafe) {
+        this.isThreadSafe = isThreadSafe;
+    }
+
+    public void shouldBeUsedInOneThread(final boolean shouldBeUsedInOneThread) {
+        this.shouldBeUsedInOneThread = shouldBeUsedInOneThread;
+    }
+
+    public boolean isThreadSafe() {
+        return this.isThreadSafe;
+    }
+
+    public void checkThreadSafety() {
+        if (!shouldBeUsedInOneThread) {
+            return;
+        }
+        if (lastThread == null) {
+            lastThread = Thread.currentThread();
+        } else if (lastThread != Thread.currentThread()) {
+            throw new AssertionErrorWrapper(new AssertionError(
+                    "\n Mock isn't supposed to be called from multiple threads. Last: " + lastThread
+                            + " Current: " + Thread.currentThread()));
+        }
+    }
+}
diff --git a/src/org/easymock/internal/MocksControl.java b/src/org/easymock/internal/MocksControl.java
index 62d2d9e..e709dc4 100644
--- a/src/org/easymock/internal/MocksControl.java
+++ b/src/org/easymock/internal/MocksControl.java
@@ -1,279 +1,392 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-
-import org.easymock.IAnswer;
-import org.easymock.IExpectationSetters;
-import org.easymock.IMocksControl;
-
-public class MocksControl implements IMocksControl, IExpectationSetters<Object>, Serializable {
-
-    private static final long serialVersionUID = 443604921336702014L;
-
-    private IMocksControlState state;
-
-    private IMocksBehavior behavior;
-
-    public enum MockType {
-        NICE, DEFAULT, STRICT
-    }
-
-    private MockType type;
-
-    public MocksControl(MockType type) {
-        this.type = type;
-        reset();
-    }
-
-    public IMocksControlState getState() {
-        return state;
-    }
-
-    public <T> T createMock(Class<T> toMock) {
-        try {
-            state.assertRecordState();
-            IProxyFactory<T> proxyFactory = createProxyFactory(toMock);
-            return proxyFactory.createProxy(toMock, new ObjectMethodsFilter(
-                    toMock, new MockInvocationHandler(this), null));
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public <T> T createMock(String name, Class<T> toMock) {
-        try {
-            state.assertRecordState();
-            IProxyFactory<T> proxyFactory = createProxyFactory(toMock);
-            return proxyFactory.createProxy(toMock, new ObjectMethodsFilter(
-                    toMock, new MockInvocationHandler(this), name));
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    protected <T> IProxyFactory<T> createProxyFactory(Class<T> toMock) {
-        return new JavaProxyFactory<T>();
-    }
-
-    public final void reset() {
-        behavior = new MocksBehavior(type == MockType.NICE);
-        behavior.checkOrder(type == MockType.STRICT);
-        behavior.makeThreadSafe(false);
-        state = new RecordState(behavior);
-        LastControl.reportLastControl(null);
-    }
-
-    public void resetToNice() {
-        type = MockType.NICE;
-        reset();
-    }
-    
-    public void resetToDefault() {
-        type = MockType.DEFAULT;
-        reset();        
-    }
-    
-    public void resetToStrict() {
-        type = MockType.STRICT;
-        reset();
-    }
-    
-    public void replay() {
-        try {
-            state.replay();
-            state = new ReplayState(behavior);
-            LastControl.reportLastControl(null);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void verify() {
-        try {
-            state.verify();
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        } catch (AssertionErrorWrapper e) {
-            throw (AssertionError) e.getAssertionError().fillInStackTrace();
-        }
-    }
-
-    public void checkOrder(boolean value) {
-        try {
-            state.checkOrder(value);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-    
-    public void makeThreadSafe(boolean threadSafe) {
-        try {
-            state.makeThreadSafe(threadSafe);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    // methods from IBehaviorSetters
-
-    public IExpectationSetters<Object> andReturn(Object value) {
-        try {
-            state.andReturn(value);
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> andThrow(Throwable throwable) {
-        try {
-            state.andThrow(throwable);
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> andAnswer(IAnswer<? extends Object> answer) {
-        try {
-            state.andAnswer(answer);
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void andStubReturn(Object value) {
-        try {
-            state.andStubReturn(value);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void andStubThrow(Throwable throwable) {
-        try {
-            state.andStubThrow(throwable);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void andStubAnswer(IAnswer<? extends Object> answer) {
-        try {
-            state.andStubAnswer(answer);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void asStub() {
-        try {
-            state.asStub();
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> times(int times) {
-        try {
-            state.times(new Range(times));
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> times(int min, int max) {
-        try {
-            state.times(new Range(min, max));
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> once() {
-        try {
-            state.times(ONCE);
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> atLeastOnce() {
-        try {
-            state.times(AT_LEAST_ONCE);
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public IExpectationSetters<Object> anyTimes() {
-        try {
-            state.times(ZERO_OR_MORE);
-            return this;
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    /**
-     * Exactly one call.
-     */
-    public static final Range ONCE = new Range(1);
-
-    /**
-     * One or more calls.
-     */
-    public static final Range AT_LEAST_ONCE = new Range(1, Integer.MAX_VALUE);
-
-    /**
-     * Zero or more calls.
-     */
-    public static final Range ZERO_OR_MORE = new Range(0, Integer.MAX_VALUE);
-
-    @SuppressWarnings("deprecation")
-    public void setLegacyDefaultMatcher(org.easymock.ArgumentsMatcher matcher) {
-        try {
-            state.setDefaultMatcher(matcher);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setLegacyMatcher(org.easymock.ArgumentsMatcher matcher) {
-        try {
-            state.setMatcher(null, matcher);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void setLegacyDefaultReturnValue(Object value) {
-        try {
-            state.setDefaultReturnValue(value);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-
-    public void setLegacyDefaultVoidCallable() {
-        state.setDefaultVoidCallable();
-    }
-
-    public void setLegacyDefaultThrowable(Throwable throwable) {
-        try {
-            state.setDefaultThrowable(throwable);
-        } catch (RuntimeExceptionWrapper e) {
-            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.easymock.*;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class MocksControl implements IMocksControl, IExpectationSetters<Object>, Serializable {
+
+    private static final long serialVersionUID = 443604921336702014L;
+
+    /** lazily created; the proxy factory for classes */
+    private static IProxyFactory classProxyFactory;
+
+    private static final IProxyFactory interfaceProxyFactory = new JavaProxyFactory();
+
+    private IMocksControlState state;
+
+    private IMocksBehavior behavior;
+
+    /**
+     * This class was kept here for compabitility reason with frameworks using EasyMock
+     * @deprecated Use org.easymock.MockType
+     */
+    @Deprecated
+    public enum MockType {
+        NICE(org.easymock.MockType.NICE),
+        DEFAULT(org.easymock.MockType.DEFAULT),
+        STRICT(org.easymock.MockType.STRICT);
+
+        public org.easymock.MockType realType;
+
+        MockType(final org.easymock.MockType realType) {
+            this.realType = realType;
+        }
+    }
+
+    private org.easymock.MockType type;
+
+    public MocksControl(final org.easymock.MockType type) {
+        this.type = type;
+        reset();
+    }
+
+    public MocksControl(final MockType type) {
+        this.type = type.realType;
+        reset();
+    }
+
+    public org.easymock.MockType getType() {
+        return type;
+    }
+
+    public IMocksControlState getState() {
+        return state;
+    }
+
+    public <T> T createMock(final Class<T> toMock) {
+        return createMock(null, toMock, (Method[]) null);
+    }
+
+    public <T> T createMock(final String name, final Class<T> toMock) {
+        return createMock(name, toMock, (Method[]) null);
+    }
+
+    @Deprecated
+    public <T> T createMock(final String name, final Class<T> toMock, final Method... mockedMethods) {
+        return createMock(name, toMock, null, mockedMethods);
+    }
+
+    @Deprecated
+    public <T> T createMock(final Class<T> toMock, final Method... mockedMethods) {
+        return createMock(null, toMock, null, mockedMethods);
+    }
+
+    @Deprecated
+    public <T> T createMock(final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        return createMock(null, toMock, constructorArgs, mockedMethods);
+    }
+
+    @Deprecated
+    public <T> T createMock(final String name, final Class<T> toMock, final ConstructorArgs constructorArgs,
+            final Method... mockedMethods) {
+        if (toMock.isInterface() && mockedMethods != null) {
+            throw new IllegalArgumentException("Partial mocking doesn't make sense for interface");
+        }
+
+        try {
+            state.assertRecordState();
+            final IProxyFactory proxyFactory = toMock.isInterface()
+                    ? interfaceProxyFactory
+                    : getClassProxyFactory();
+            return proxyFactory.createProxy(toMock, new ObjectMethodsFilter(toMock,
+                    new MockInvocationHandler(this), name), mockedMethods, constructorArgs);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public static IProxyFactory getProxyFactory(final Object o) {
+        return Proxy.isProxyClass(o.getClass())
+                ? new JavaProxyFactory()
+                : getClassProxyFactory();
+    }
+
+    private static IProxyFactory getClassProxyFactory() {
+        final String classMockingDisabled = EasyMockProperties.getInstance().getProperty(
+                EasyMock.DISABLE_CLASS_MOCKING);
+        if (Boolean.valueOf(classMockingDisabled)) {
+            throw new IllegalArgumentException("Class mocking is currently disabled. Change "
+                    + EasyMock.DISABLE_CLASS_MOCKING + " to true do modify this behavior");
+        }
+
+        final IProxyFactory cached = classProxyFactory;
+        if (cached != null) {
+            return cached;
+        }
+
+        // ///CLOVER:OFF
+        if (AndroidSupport.isAndroid()) {
+            return classProxyFactory = new AndroidClassProxyFactory();
+        }
+        // ///CLOVER:ON
+
+        try {
+            return classProxyFactory = new ClassProxyFactory();
+        } catch (final NoClassDefFoundError e) {
+            throw new RuntimeException(
+                    "Class mocking requires to have cglib and objenesis librairies in the classpath", e);
+        }
+    }
+
+    public static MocksControl getControl(final Object mock) {
+        try {
+            final IProxyFactory factory = getProxyFactory(mock);
+            final ObjectMethodsFilter handler = (ObjectMethodsFilter) factory.getInvocationHandler(mock);
+            return handler.getDelegate().getControl();
+        } catch (final ClassCastException e) {
+            throw new IllegalArgumentException("Not a mock: " + mock.getClass().getName());
+        }
+    }
+
+    public static InvocationHandler getInvocationHandler(final Object mock) {
+        return getClassProxyFactory().getInvocationHandler(mock);
+    }
+
+    /**
+     * Return the class of interface (depending on the mock type) that was
+     * mocked
+     *
+     * @param <T>
+     *            Mocked class
+     * @param <V>
+     *            Mock class
+     * @param proxy
+     *            Mock object
+     * @return the mocked class or interface
+     */
+    @SuppressWarnings("unchecked")
+    public static <T, V extends T> Class<T> getMockedType(final V proxy) {
+        if (Proxy.isProxyClass(proxy.getClass())) {
+            return (Class<T>) proxy.getClass().getInterfaces()[0];
+        }
+        return (Class<T>) proxy.getClass().getSuperclass();
+    }
+
+    public final void reset() {
+        behavior = new MocksBehavior(type == org.easymock.MockType.NICE);
+        behavior.checkOrder(type == org.easymock.MockType.STRICT);
+        state = new RecordState(behavior);
+        LastControl.reportLastControl(null);
+    }
+
+    public void resetToNice() {
+        type = org.easymock.MockType.NICE;
+        reset();
+    }
+
+    public void resetToDefault() {
+        type = org.easymock.MockType.DEFAULT;
+        reset();
+    }
+
+    public void resetToStrict() {
+        type = org.easymock.MockType.STRICT;
+        reset();
+    }
+
+    public void replay() {
+        try {
+            state.replay();
+            state = new ReplayState(behavior);
+            LastControl.reportLastControl(null);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void verify() {
+        try {
+            state.verify();
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        } catch (final AssertionErrorWrapper e) {
+            throw (AssertionError) e.getAssertionError().fillInStackTrace();
+        }
+    }
+
+    public void checkOrder(final boolean value) {
+        try {
+            state.checkOrder(value);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void makeThreadSafe(final boolean threadSafe) {
+        try {
+            state.makeThreadSafe(threadSafe);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void checkIsUsedInOneThread(final boolean shouldBeUsedInOneThread) {
+        try {
+            state.checkIsUsedInOneThread(shouldBeUsedInOneThread);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    // methods from IBehaviorSetters
+
+    public IExpectationSetters<Object> andReturn(final Object value) {
+        try {
+            state.andReturn(value);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> andThrow(final Throwable throwable) {
+        try {
+            state.andThrow(throwable);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> andAnswer(final IAnswer<? extends Object> answer) {
+        try {
+            state.andAnswer(answer);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> andDelegateTo(final Object answer) {
+        try {
+            state.andDelegateTo(answer);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void andStubReturn(final Object value) {
+        try {
+            state.andStubReturn(value);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void andStubThrow(final Throwable throwable) {
+        try {
+            state.andStubThrow(throwable);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void andStubAnswer(final IAnswer<? extends Object> answer) {
+        try {
+            state.andStubAnswer(answer);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void andStubDelegateTo(final Object delegateTo) {
+        try {
+            state.andStubDelegateTo(delegateTo);
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public void asStub() {
+        try {
+            state.asStub();
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> times(final int times) {
+        try {
+            state.times(new Range(times));
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> times(final int min, final int max) {
+        try {
+            state.times(new Range(min, max));
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> once() {
+        try {
+            state.times(ONCE);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> atLeastOnce() {
+        try {
+            state.times(AT_LEAST_ONCE);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    public IExpectationSetters<Object> anyTimes() {
+        try {
+            state.times(ZERO_OR_MORE);
+            return this;
+        } catch (final RuntimeExceptionWrapper e) {
+            throw (RuntimeException) e.getRuntimeException().fillInStackTrace();
+        }
+    }
+
+    /**
+     * Exactly one call.
+     */
+    public static final Range ONCE = new Range(1);
+
+    /**
+     * One or more calls.
+     */
+    public static final Range AT_LEAST_ONCE = new Range(1, Integer.MAX_VALUE);
+
+    /**
+     * Zero or more calls.
+     */
+    public static final Range ZERO_OR_MORE = new Range(0, Integer.MAX_VALUE);
+
+}
diff --git a/src/org/easymock/internal/ObjectMethodsFilter.java b/src/org/easymock/internal/ObjectMethodsFilter.java
index e85a168..0384896 100644
--- a/src/org/easymock/internal/ObjectMethodsFilter.java
+++ b/src/org/easymock/internal/ObjectMethodsFilter.java
@@ -1,98 +1,127 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-public class ObjectMethodsFilter implements InvocationHandler, Serializable {
-
-    private static final long serialVersionUID = -2120581954279966998L;
-
-    private transient Method equalsMethod;
-
-    private transient Method hashCodeMethod;
-
-    private transient Method toStringMethod;
-
-    private final MockInvocationHandler delegate;
-
-    private final String name;
-
-    public ObjectMethodsFilter(Class<?> toMock, MockInvocationHandler delegate,
-            String name) {
-        if (name != null && !Invocation.isJavaIdentifier(name)) {
-            throw new IllegalArgumentException(String.format("'%s' is not a valid Java identifier.", name));
-            
-        }
-        try {
-            if (toMock.isInterface()) {
-                toMock = Object.class;
-            }
-            equalsMethod = toMock.getMethod("equals",
-                    new Class[] { Object.class });
-            hashCodeMethod = toMock.getMethod("hashCode", (Class[]) null);
-            toStringMethod = toMock.getMethod("toString", (Class[]) null);
-        } catch (NoSuchMethodException e) {
-            // ///CLOVER:OFF
-            throw new RuntimeException("An Object method could not be found!");
-            // ///CLOVER:ON
-        }
-        this.delegate = delegate;
-        this.name = name;
-    }
-
-    public final Object invoke(Object proxy, Method method, Object[] args)
-            throws Throwable {
-        if (equalsMethod.equals(method)) {
-            return Boolean.valueOf(proxy == args[0]);
-        }
-        if (hashCodeMethod.equals(method)) {
-            return Integer.valueOf(System.identityHashCode(proxy));
-        }
-        if (toStringMethod.equals(method)) {
-            return mockToString(proxy);
-        }
-        return delegate.invoke(proxy, method, args);
-    }
-
-    private String mockToString(Object proxy) {
-        return (name != null) ? name : "EasyMock for " + mockType(proxy);
-    }
-
-    private String mockType(Object proxy) {
-        if (Proxy.isProxyClass(proxy.getClass()))
-            return proxy.getClass().getInterfaces()[0].toString();
-        else
-            return proxy.getClass().getSuperclass().toString();
-    }
-
-    public MockInvocationHandler getDelegate() {
-        return delegate;
-    }
-    
-    private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
-        stream.defaultReadObject();
-        try {
-            toStringMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
-            equalsMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
-            hashCodeMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
-        } catch (NoSuchMethodException e) {
-            // ///CLOVER:OFF
-            throw new IOException(e.toString());
-            // ///CLOVER:ON
-        }
-    }
-    
-    private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
-        stream.defaultWriteObject();
-        stream.writeObject(new MethodSerializationWrapper(toStringMethod));
-        stream.writeObject(new MethodSerializationWrapper(equalsMethod));
-        stream.writeObject(new MethodSerializationWrapper(hashCodeMethod));
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * @author OFFIS, Tammo Freese
+ * @author Henri Tremblay
+ */
+public class ObjectMethodsFilter implements InvocationHandler, Serializable {
+
+    private static final long serialVersionUID = -1726286682930686024L;
+
+    private transient Method equalsMethod;
+
+    private transient Method hashCodeMethod;
+
+    private transient Method toStringMethod;
+
+    private transient Method finalizeMethod;
+
+    private final MockInvocationHandler delegate;
+
+    private final String name;
+
+    public ObjectMethodsFilter(final Class<?> toMock, final MockInvocationHandler delegate, final String name) {
+        if (name != null && !Invocation.isJavaIdentifier(name)) {
+            throw new IllegalArgumentException(String.format("'%s' is not a valid Java identifier.", name));
+
+        }
+
+        if (toMock.isInterface()) {
+            equalsMethod = ReflectionUtils.OBJECT_EQUALS;
+            hashCodeMethod = ReflectionUtils.OBJECT_HASHCODE;
+            toStringMethod = ReflectionUtils.OBJECT_TOSTRING;
+            finalizeMethod = ReflectionUtils.OBJECT_FINALIZE;
+        } else {
+            try {
+                equalsMethod = extractMethod(toMock, "equals", Object.class);
+                hashCodeMethod = extractMethod(toMock, "hashCode", (Class[]) null);
+                toStringMethod = extractMethod(toMock, "toString", (Class[]) null);
+                finalizeMethod = ReflectionUtils.findMethod(toMock, "finalize", (Class[]) null);
+            } catch (final NoSuchMethodException e) {
+                // ///CLOVER:OFF
+                throw new RuntimeException("An Object method could not be found!", e);
+                // ///CLOVER:ON
+            }
+        }
+
+        this.delegate = delegate;
+        this.name = name;
+    }
+
+    private static Method extractMethod(Class<?> toMock, String name, Class<?>... params) throws NoSuchMethodException {
+        Method m = toMock.getMethod(name, params);
+        // It can occur that the method was bridged. Usually, this means the method was in package scope on a parent class
+        // When that occurs, we need to resolve the bridge to always extract the real method
+        if(m.isBridge()) {
+            m = BridgeMethodResolver.findBridgedMethod(m);
+        }
+        return m;
+    }
+
+    public final Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        if (equalsMethod.equals(method)) {
+            return Boolean.valueOf(proxy == args[0]);
+        }
+        if (hashCodeMethod.equals(method)) {
+            return Integer.valueOf(System.identityHashCode(proxy));
+        }
+        if (toStringMethod.equals(method)) {
+            return mockToString(proxy);
+        }
+        if (finalizeMethod.equals(method)) {
+            return null; // ignore finalize completely to prevent any unexpected side-effect from the GC
+        }
+        return delegate.invoke(proxy, method, args);
+    }
+
+    private String mockToString(final Object proxy) {
+        return (name != null) ? name : "EasyMock for " + MocksControl.getMockedType(proxy);
+    }
+
+    public MockInvocationHandler getDelegate() {
+        return delegate;
+    }
+
+    private void readObject(final java.io.ObjectInputStream stream) throws IOException,
+            ClassNotFoundException {
+        stream.defaultReadObject();
+        try {
+            toStringMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
+            equalsMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
+            hashCodeMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
+            finalizeMethod = ((MethodSerializationWrapper) stream.readObject()).getMethod();
+        } catch (final NoSuchMethodException e) {
+            // ///CLOVER:OFF
+            throw new IOException(e.toString());
+            // ///CLOVER:ON
+        }
+    }
+
+    private void writeObject(final java.io.ObjectOutputStream stream) throws IOException {
+        stream.defaultWriteObject();
+        stream.writeObject(new MethodSerializationWrapper(toStringMethod));
+        stream.writeObject(new MethodSerializationWrapper(equalsMethod));
+        stream.writeObject(new MethodSerializationWrapper(hashCodeMethod));
+        stream.writeObject(new MethodSerializationWrapper(finalizeMethod));
+    }
 }
\ No newline at end of file
diff --git a/src/org/easymock/internal/ObjenesisClassInstantiator.java b/src/org/easymock/internal/ObjenesisClassInstantiator.java
new file mode 100644
index 0000000..a3a5d81
--- /dev/null
+++ b/src/org/easymock/internal/ObjenesisClassInstantiator.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import org.objenesis.ObjenesisHelper;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ObjenesisClassInstantiator implements IClassInstantiator {
+
+    public Object newInstance(final Class<?> clazz) throws InstantiationException {
+        return ObjenesisHelper.newInstance(clazz);
+    }
+
+}
diff --git a/src/org/easymock/internal/Range.java b/src/org/easymock/internal/Range.java
index 61b5faa..98e2742 100644
--- a/src/org/easymock/internal/Range.java
+++ b/src/org/easymock/internal/Range.java
@@ -1,73 +1,85 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-
-public class Range implements Serializable {
-
-    private static final long serialVersionUID = -6743402320315331536L;
-
-    private int minimum;
-
-    private int maximum;
-
-    public Range(int count) {
-        this(count, count);
-    }
-
-    public Range(int minimum, int maximum) {
-        if (!(minimum <= maximum)) {
-            throw new RuntimeExceptionWrapper(new IllegalArgumentException(
-                    "minimum must be <= maximum"));
-        }
-
-        if (!(minimum >= 0)) {
-            throw new RuntimeExceptionWrapper(new IllegalArgumentException(
-                    "minimum must be >= 0"));
-        }
-
-        if (!(maximum >= 1)) {
-            throw new RuntimeExceptionWrapper(new IllegalArgumentException(
-                    "maximum must be >= 1"));
-        }
-        this.minimum = minimum;
-        this.maximum = maximum;
-    }
-
-    public boolean hasFixedCount() {
-        return minimum == maximum;
-    }
-
-    public int getMaximum() {
-        return maximum;
-    }
-
-    public int getMinimum() {
-        return minimum;
-    }
-
-    public String toString() {
-        if (hasFixedCount()) {
-            return "" + minimum;
-        } else if (hasOpenCount()) {
-            return "at least " + minimum;
-        } else {
-            return "between " + minimum + " and " + maximum;
-        }
-    }
-
-    public String expectedAndActual(int count) {
-        return "expected: " + this.toString() + ", actual: " + count;
-    }
-
-    public boolean contains(int count) {
-        return minimum <= count && count <= maximum;
-    }
-
-    public boolean hasOpenCount() {
-        return maximum == Integer.MAX_VALUE;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Range implements Serializable {
+
+    private static final long serialVersionUID = -6743402320315331536L;
+
+    private final int minimum;
+
+    private final int maximum;
+
+    public Range(final int count) {
+        this(count, count);
+    }
+
+    public Range(final int minimum, final int maximum) {
+        if (!(minimum <= maximum)) {
+            throw new RuntimeExceptionWrapper(new IllegalArgumentException("minimum must be <= maximum"));
+        }
+
+        if (!(minimum >= 0)) {
+            throw new RuntimeExceptionWrapper(new IllegalArgumentException("minimum must be >= 0"));
+        }
+
+        if (!(maximum >= 1)) {
+            throw new RuntimeExceptionWrapper(new IllegalArgumentException("maximum must be >= 1"));
+        }
+        this.minimum = minimum;
+        this.maximum = maximum;
+    }
+
+    public boolean hasFixedCount() {
+        return minimum == maximum;
+    }
+
+    public int getMaximum() {
+        return maximum;
+    }
+
+    public int getMinimum() {
+        return minimum;
+    }
+
+    @Override
+    public String toString() {
+        if (hasFixedCount()) {
+            return "" + minimum;
+        } else if (hasOpenCount()) {
+            return "at least " + minimum;
+        } else {
+            return "between " + minimum + " and " + maximum;
+        }
+    }
+
+    public String expectedCount() {
+        return "expected: " + this.toString();
+    }
+
+    public boolean contains(final int count) {
+        return minimum <= count && count <= maximum;
+    }
+
+    public boolean hasOpenCount() {
+        return maximum == Integer.MAX_VALUE;
+    }
+}
diff --git a/src/org/easymock/internal/RecordState.java b/src/org/easymock/internal/RecordState.java
index 7fb4892..7d767f9 100644
--- a/src/org/easymock/internal/RecordState.java
+++ b/src/org/easymock/internal/RecordState.java
@@ -1,346 +1,342 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.easymock.IAnswer;
-import org.easymock.IArgumentMatcher;
-
-public class RecordState implements IMocksControlState, Serializable {
-
-    private static final long serialVersionUID = -5418279681566430252L;
-
-    private ExpectedInvocation lastInvocation;
-
-    private boolean lastInvocationUsed = true;
-
-    private Result lastResult;
-
-    private IMocksBehavior behavior;
-
-    private static Map<Class<?>, Object> emptyReturnValues = new HashMap<Class<?>, Object>();
-
-    static {
-        emptyReturnValues.put(Void.TYPE, null);
-        emptyReturnValues.put(Boolean.TYPE, Boolean.FALSE);
-        emptyReturnValues.put(Byte.TYPE, new Byte((byte) 0));
-        emptyReturnValues.put(Short.TYPE, new Short((short) 0));
-        emptyReturnValues.put(Character.TYPE, new Character((char) 0));
-        emptyReturnValues.put(Integer.TYPE, new Integer(0));
-        emptyReturnValues.put(Long.TYPE, new Long(0));
-        emptyReturnValues.put(Float.TYPE, new Float(0));
-        emptyReturnValues.put(Double.TYPE, new Double(0));
-    }
-
-    private static Map<Class<?>, Class<?>> primitiveToWrapperType = new HashMap<Class<?>, Class<?>>();
-
-    static {
-        primitiveToWrapperType.put(Boolean.TYPE, Boolean.class);
-        primitiveToWrapperType.put(Byte.TYPE, Byte.class);
-        primitiveToWrapperType.put(Short.TYPE, Short.class);
-        primitiveToWrapperType.put(Character.TYPE, Character.class);
-        primitiveToWrapperType.put(Integer.TYPE, Integer.class);
-        primitiveToWrapperType.put(Long.TYPE, Long.class);
-        primitiveToWrapperType.put(Float.TYPE, Float.class);
-        primitiveToWrapperType.put(Double.TYPE, Double.class);
-    }
-
-    public RecordState(IMocksBehavior behavior) {
-        this.behavior = behavior;
-    }
-
-    public void assertRecordState() {
-    }
-
-    public java.lang.Object invoke(Invocation invocation) {
-        closeMethod();
-        List<IArgumentMatcher> lastMatchers = LastControl.pullMatchers();
-        lastInvocation = new ExpectedInvocation(invocation, lastMatchers);
-        lastInvocationUsed = false;
-        return emptyReturnValueFor(invocation.getMethod().getReturnType());
-    }
-
-    public void replay() {
-        closeMethod();
-        if (LastControl.pullMatchers() != null) {
-            throw new IllegalStateException("matcher calls were used outside expectations");
-        }
-    }
-
-    public void verify() {
-        throw new RuntimeExceptionWrapper(new IllegalStateException(
-                "calling verify is not allowed in record state"));
-    }
-
-    public void andReturn(Object value) {
-        requireMethodCall("return value");
-        value = convertNumberClassIfNeccessary(value);
-        requireAssignable(value);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        lastResult = Result.createReturnResult(value);
-    }
-
-    public void andThrow(Throwable throwable) {
-        requireMethodCall("Throwable");
-        requireValidThrowable(throwable);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        lastResult = Result.createThrowResult(throwable);
-    }
-    
-    public void andAnswer(IAnswer<?> answer) {
-        requireMethodCall("answer");
-        requireValidAnswer(answer);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        lastResult = Result.createAnswerResult(answer);
-    }
-
-    public void andStubReturn(Object value) {
-        requireMethodCall("stub return value");
-        value = convertNumberClassIfNeccessary(value);
-        requireAssignable(value);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        behavior.addStub(lastInvocation, Result.createReturnResult(value));
-        lastInvocationUsed = true;
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setDefaultReturnValue(Object value) {
-        requireMethodCall("default return value");
-        value = convertNumberClassIfNeccessary(value);
-        requireAssignable(value);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        behavior.addStub(
-                lastInvocation.withMatcher(org.easymock.MockControl.ALWAYS_MATCHER), Result
-                        .createReturnResult(value));
-        lastInvocationUsed = true;
-    }
-
-    public void asStub() {
-        requireMethodCall("stub behavior");
-        requireVoidMethod();
-        behavior.addStub(lastInvocation, Result.createReturnResult(null));
-        lastInvocationUsed = true;
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setDefaultVoidCallable() {
-        requireMethodCall("default void callable");
-        requireVoidMethod();
-        behavior.addStub(
-                lastInvocation.withMatcher(org.easymock.MockControl.ALWAYS_MATCHER), Result
-                        .createReturnResult(null));
-        lastInvocationUsed = true;
-    }
-
-    public void andStubThrow(Throwable throwable) {
-        requireMethodCall("stub Throwable");
-        requireValidThrowable(throwable);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        behavior.addStub(lastInvocation, Result.createThrowResult(throwable));
-        lastInvocationUsed = true;
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setDefaultThrowable(Throwable throwable) {
-        requireMethodCall("default Throwable");
-        requireValidThrowable(throwable);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        behavior.addStub(
-                lastInvocation.withMatcher(org.easymock.MockControl.ALWAYS_MATCHER), Result
-                        .createThrowResult(throwable));
-        lastInvocationUsed = true;
-    }
-
-    public void andStubAnswer(IAnswer<?> answer) {
-        requireMethodCall("stub answer");
-        requireValidAnswer(answer);
-        if (lastResult != null) {
-            times(MocksControl.ONCE);
-        }
-        behavior.addStub(lastInvocation, Result.createAnswerResult(answer));
-        lastInvocationUsed = true;
-    }
-
-    public void times(Range range) {
-        requireMethodCall("times");
-        requireLastResultOrVoidMethod();
-
-        behavior.addExpected(lastInvocation, lastResult != null ? lastResult
-                : Result.createReturnResult(null), range);
-        lastInvocationUsed = true;
-        lastResult = null;
-    }
-
-    private Object createNumberObject(Object value, Class<?> returnType) {
-        if (!(value instanceof Number)) {
-            return value;
-        }
-        Number number = (Number) value;        
-        if (returnType.equals(Byte.TYPE)) {
-            return number.byteValue();
-        } else if (returnType.equals(Short.TYPE)) {
-            return number.shortValue();
-        } else if (returnType.equals(Character.TYPE)) {
-            return (char) number.intValue();
-        } else if (returnType.equals(Integer.TYPE)) {
-            return number.intValue();
-        } else if (returnType.equals(Long.TYPE)) {
-            return number.longValue();
-        } else if (returnType.equals(Float.TYPE)) {
-            return number.floatValue();
-        } else if (returnType.equals(Double.TYPE)) {
-            return number.doubleValue();
-        } else {
-            return number;
-        }
-    }
-
-    private Object convertNumberClassIfNeccessary(Object o) {
-        Class<?> returnType = lastInvocation.getMethod().getReturnType();
-        return createNumberObject(o, returnType);
-    }
-
-    @SuppressWarnings("deprecation")
-    private void closeMethod() {
-        if (lastInvocationUsed && lastResult == null) {
-            return;
-        }
-        if (!isLastResultOrVoidMethod()) {
-            throw new RuntimeExceptionWrapper(new IllegalStateException(
-                    "missing behavior definition for the preceeding method call "
-                            + lastInvocation.toString()));
-        }
-        this.times(org.easymock.MockControl.ONE);
-    }
-
-    public static Object emptyReturnValueFor(Class<?> type) {
-        return type.isPrimitive() ? emptyReturnValues.get(type) : null;
-    }
-
-    private void requireMethodCall(String failMessage) {
-        if (lastInvocation == null) {
-            throw new RuntimeExceptionWrapper(new IllegalStateException(
-                    "method call on the mock needed before setting "
-                            + failMessage));
-        }
-    }
-
-    private void requireAssignable(Object returnValue) {
-        if (lastMethodIsVoidMethod()) {
-            throw new RuntimeExceptionWrapper(new IllegalStateException(
-                    "void method cannot return a value"));
-        }
-        if (returnValue == null) {
-            return;
-        }
-        Class<?> returnedType = lastInvocation.getMethod().getReturnType();
-        if (returnedType.isPrimitive()) {
-            returnedType = primitiveToWrapperType.get(returnedType);
-
-        }
-        if (!returnedType.isAssignableFrom(returnValue.getClass())) {
-            throw new RuntimeExceptionWrapper(new IllegalStateException(
-                    "incompatible return value type"));
-        }
-    }
-
-    private void requireValidThrowable(Throwable throwable) {
-        if (throwable == null)
-            throw new RuntimeExceptionWrapper(new NullPointerException(
-                    "null cannot be thrown"));
-        if (isValidThrowable(throwable))
-            return;
-
-        throw new RuntimeExceptionWrapper(new IllegalArgumentException(
-                "last method called on mock cannot throw "
-                        + throwable.getClass().getName()));
-    }
-
-    private void requireValidAnswer(IAnswer<?> answer) {
-        if (answer == null)
-            throw new RuntimeExceptionWrapper(new NullPointerException(
-                    "answer object must not be null"));
-    }
-
-    private void requireLastResultOrVoidMethod() {
-        if (isLastResultOrVoidMethod()) {
-            return;
-        }
-        throw new RuntimeExceptionWrapper(new IllegalStateException(
-                "last method called on mock is not a void method"));
-    }
-
-    private void requireVoidMethod() {
-        if (lastMethodIsVoidMethod()) {
-            return;
-        }
-        throw new RuntimeExceptionWrapper(new IllegalStateException(
-                "last method called on mock is not a void method"));
-    }
-
-    private boolean isLastResultOrVoidMethod() {
-        return lastResult != null || lastMethodIsVoidMethod();
-    }
-
-    private boolean lastMethodIsVoidMethod() {
-        Class<?> returnType = lastInvocation.getMethod().getReturnType();
-        return returnType.equals(Void.TYPE);
-    }
-
-    private boolean isValidThrowable(Throwable throwable) {
-        if (throwable instanceof RuntimeException) {
-            return true;
-        }
-        if (throwable instanceof Error) {
-            return true;
-        }
-        Class<?>[] exceptions = lastInvocation.getMethod().getExceptionTypes();
-        Class<?> throwableClass = throwable.getClass();
-        for (Class<?> exception : exceptions) {
-            if (exception.isAssignableFrom(throwableClass))
-                return true;
-        }
-        return false;
-    }
-
-    public void checkOrder(boolean value) {
-        closeMethod();
-        behavior.checkOrder(value);
-    }
-
-    public void makeThreadSafe(boolean threadSafe) {
-        behavior.makeThreadSafe(threadSafe);
-    }
-    
-    @SuppressWarnings("deprecation")
-    public void setDefaultMatcher(org.easymock.ArgumentsMatcher matcher) {
-        behavior.setDefaultMatcher(matcher);
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setMatcher(Method method, org.easymock.ArgumentsMatcher matcher) {
-        requireMethodCall("matcher");
-        behavior.setMatcher(lastInvocation.getMethod(), matcher);
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.IAnswer;
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordState implements IMocksControlState, Serializable {
+
+    private static final long serialVersionUID = -5418279681566430252L;
+
+    private ExpectedInvocation lastInvocation = null;
+
+    private boolean lastInvocationUsed = true;
+
+    private Result lastResult;
+
+    private final IMocksBehavior behavior;
+
+    private static Map<Class<?>, Object> emptyReturnValues = new HashMap<Class<?>, Object>();
+
+    static {
+        emptyReturnValues.put(Void.TYPE, null);
+        emptyReturnValues.put(Boolean.TYPE, Boolean.FALSE);
+        emptyReturnValues.put(Byte.TYPE, Byte.valueOf((byte) 0));
+        emptyReturnValues.put(Short.TYPE, Short.valueOf((short) 0));
+        emptyReturnValues.put(Character.TYPE, Character.valueOf((char) 0));
+        emptyReturnValues.put(Integer.TYPE, Integer.valueOf(0));
+        emptyReturnValues.put(Long.TYPE, Long.valueOf(0));
+        emptyReturnValues.put(Float.TYPE, Float.valueOf(0));
+        emptyReturnValues.put(Double.TYPE, Double.valueOf(0));
+    }
+
+    private static Map<Class<?>, Class<?>> primitiveToWrapperType = new HashMap<Class<?>, Class<?>>();
+
+    static {
+        primitiveToWrapperType.put(Boolean.TYPE, Boolean.class);
+        primitiveToWrapperType.put(Byte.TYPE, Byte.class);
+        primitiveToWrapperType.put(Short.TYPE, Short.class);
+        primitiveToWrapperType.put(Character.TYPE, Character.class);
+        primitiveToWrapperType.put(Integer.TYPE, Integer.class);
+        primitiveToWrapperType.put(Long.TYPE, Long.class);
+        primitiveToWrapperType.put(Float.TYPE, Float.class);
+        primitiveToWrapperType.put(Double.TYPE, Double.class);
+    }
+
+    public RecordState(final IMocksBehavior behavior) {
+        this.behavior = behavior;
+    }
+
+    public void assertRecordState() {
+    }
+
+    public java.lang.Object invoke(final Invocation invocation) {
+        closeMethod();
+        final List<IArgumentMatcher> lastMatchers = LastControl.pullMatchers();
+        lastInvocation = new ExpectedInvocation(invocation, lastMatchers);
+        lastInvocationUsed = false;
+        return emptyReturnValueFor(invocation.getMethod().getReturnType());
+    }
+
+    public void replay() {
+        closeMethod();
+        if (LastControl.pullMatchers() != null) {
+            throw new IllegalStateException("matcher calls were used outside expectations");
+        }
+    }
+
+    public void verify() {
+        throw new RuntimeExceptionWrapper(new IllegalStateException(
+                "calling verify is not allowed in record state"));
+    }
+
+    public void andReturn(Object value) {
+        requireMethodCall("return value");
+        value = convertNumberClassIfNeccessary(value);
+        requireAssignable(value);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        lastResult = Result.createReturnResult(value);
+    }
+
+    public void andThrow(final Throwable throwable) {
+        requireMethodCall("Throwable");
+        requireValidThrowable(throwable);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        lastResult = Result.createThrowResult(throwable);
+    }
+
+    public void andAnswer(final IAnswer<?> answer) {
+        requireMethodCall("answer");
+        requireValidAnswer(answer);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        lastResult = Result.createAnswerResult(answer);
+    }
+
+    public void andDelegateTo(final Object delegateTo) {
+        requireMethodCall("delegate");
+        requireValidDelegation(delegateTo);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        lastResult = Result.createDelegatingResult(delegateTo);
+    }
+
+    public void andStubReturn(Object value) {
+        requireMethodCall("stub return value");
+        value = convertNumberClassIfNeccessary(value);
+        requireAssignable(value);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        behavior.addStub(lastInvocation, Result.createReturnResult(value));
+        lastInvocationUsed = true;
+    }
+
+    public void asStub() {
+        requireMethodCall("stub behavior");
+        requireVoidMethod();
+        behavior.addStub(lastInvocation, Result.createReturnResult(null));
+        lastInvocationUsed = true;
+    }
+
+    public void andStubThrow(final Throwable throwable) {
+        requireMethodCall("stub Throwable");
+        requireValidThrowable(throwable);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        behavior.addStub(lastInvocation, Result.createThrowResult(throwable));
+        lastInvocationUsed = true;
+    }
+
+    public void andStubAnswer(final IAnswer<?> answer) {
+        requireMethodCall("stub answer");
+        requireValidAnswer(answer);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        behavior.addStub(lastInvocation, Result.createAnswerResult(answer));
+        lastInvocationUsed = true;
+    }
+
+    public void andStubDelegateTo(final Object delegateTo) {
+        requireMethodCall("stub delegate");
+        requireValidDelegation(delegateTo);
+        if (lastResult != null) {
+            times(MocksControl.ONCE);
+        }
+        behavior.addStub(lastInvocation, Result.createDelegatingResult(delegateTo));
+        lastInvocationUsed = true;
+    }
+
+    public void times(final Range range) {
+        requireMethodCall("times");
+        requireLastResultOrVoidMethod();
+        behavior.addExpected(lastInvocation, lastResult != null ? lastResult : Result
+                .createReturnResult(null), range);
+        lastInvocationUsed = true;
+        lastResult = null;
+    }
+
+    private Object createNumberObject(final Object value, final Class<?> returnType) {
+        if (!(value instanceof Number)) {
+            return value;
+        }
+        final Number number = (Number) value;
+        if (returnType.equals(Byte.TYPE)) {
+            return number.byteValue();
+        } else if (returnType.equals(Short.TYPE)) {
+            return number.shortValue();
+        } else if (returnType.equals(Integer.TYPE)) {
+            return number.intValue();
+        } else if (returnType.equals(Long.TYPE)) {
+            return number.longValue();
+        } else if (returnType.equals(Float.TYPE)) {
+            return number.floatValue();
+        } else if (returnType.equals(Double.TYPE)) {
+            return number.doubleValue();
+        } else {
+            return number;
+        }
+    }
+
+    private Object convertNumberClassIfNeccessary(final Object o) {
+        final Class<?> returnType = lastInvocation.getMethod().getReturnType();
+        return createNumberObject(o, returnType);
+    }
+
+    private void closeMethod() {
+        if (lastInvocationUsed && lastResult == null) {
+            return;
+        }
+        if (!isLastResultOrVoidMethod()) {
+            throw new RuntimeExceptionWrapper(new IllegalStateException(
+                    "missing behavior definition for the preceding method call:\n"
+                            + lastInvocation.toString() + "\nUsage is: expect(a.foo()).andXXX()"));
+        }
+        times(MocksControl.ONCE);
+    }
+
+    public static Object emptyReturnValueFor(final Class<?> type) {
+        return type.isPrimitive() ? emptyReturnValues.get(type) : null;
+    }
+
+    private void requireMethodCall(final String failMessage) {
+        if (lastInvocation == null) {
+            throw new RuntimeExceptionWrapper(new IllegalStateException(
+                    "method call on the mock needed before setting " + failMessage));
+        }
+    }
+
+    private void requireAssignable(final Object returnValue) {
+        if (lastMethodIsVoidMethod()) {
+            throw new RuntimeExceptionWrapper(new IllegalStateException("void method cannot return a value"));
+        }
+        if (returnValue == null) {
+            final Class<?> returnedType = lastInvocation.getMethod().getReturnType();
+            if (returnedType.isPrimitive()) {
+                throw new RuntimeExceptionWrapper(new IllegalStateException(
+                        "can't return null for a method returning a primitive type"));
+            }
+            return;
+        }
+        Class<?> returnedType = lastInvocation.getMethod().getReturnType();
+        if (returnedType.isPrimitive()) {
+            returnedType = primitiveToWrapperType.get(returnedType);
+
+        }
+        if (!returnedType.isAssignableFrom(returnValue.getClass())) {
+            throw new RuntimeExceptionWrapper(new IllegalStateException("incompatible return value type"));
+        }
+    }
+
+    private void requireValidThrowable(final Throwable throwable) {
+        if (throwable == null) {
+            throw new RuntimeExceptionWrapper(new NullPointerException("null cannot be thrown"));
+        }
+        if (isValidThrowable(throwable)) {
+            return;
+        }
+
+        throw new RuntimeExceptionWrapper(new IllegalArgumentException(
+                "last method called on mock cannot throw " + throwable.getClass().getName()));
+    }
+
+    private void requireValidAnswer(final IAnswer<?> answer) {
+        if (answer == null) {
+            throw new RuntimeExceptionWrapper(new NullPointerException("answer object must not be null"));
+        }
+    }
+
+    private void requireValidDelegation(final Object delegateTo) {
+        if (delegateTo == null) {
+            throw new RuntimeExceptionWrapper(
+                    new NullPointerException("delegated to object must not be null"));
+        }
+        // Would be nice to validate delegateTo is implementing the mock
+        // interface (not possible right now)
+    }
+
+    private void requireLastResultOrVoidMethod() {
+        if (isLastResultOrVoidMethod()) {
+            return;
+        }
+        throw new RuntimeExceptionWrapper(new IllegalStateException(
+                "last method called on mock is not a void method"));
+    }
+
+    private void requireVoidMethod() {
+        if (lastMethodIsVoidMethod()) {
+            return;
+        }
+        throw new RuntimeExceptionWrapper(new IllegalStateException(
+                "last method called on mock is not a void method"));
+    }
+
+    private boolean isLastResultOrVoidMethod() {
+        return lastResult != null || lastMethodIsVoidMethod();
+    }
+
+    private boolean lastMethodIsVoidMethod() {
+        final Class<?> returnType = lastInvocation.getMethod().getReturnType();
+        return returnType.equals(Void.TYPE);
+    }
+
+    private boolean isValidThrowable(final Throwable throwable) {
+        if (throwable instanceof RuntimeException) {
+            return true;
+        }
+        if (throwable instanceof Error) {
+            return true;
+        }
+        final Class<?>[] exceptions = lastInvocation.getMethod().getExceptionTypes();
+        final Class<?> throwableClass = throwable.getClass();
+        for (final Class<?> exception : exceptions) {
+            if (exception.isAssignableFrom(throwableClass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void checkOrder(final boolean value) {
+        closeMethod();
+        behavior.checkOrder(value);
+    }
+
+    public void makeThreadSafe(final boolean threadSafe) {
+        behavior.makeThreadSafe(threadSafe);
+    }
+
+    public void checkIsUsedInOneThread(final boolean shouldBeUsedInOneThread) {
+        behavior.shouldBeUsedInOneThread(shouldBeUsedInOneThread);
+    }
 }
\ No newline at end of file
diff --git a/src/org/easymock/internal/ReflectionUtils.java b/src/org/easymock/internal/ReflectionUtils.java
new file mode 100644
index 0000000..8d62b4b
--- /dev/null
+++ b/src/org/easymock/internal/ReflectionUtils.java
@@ -0,0 +1,233 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Henri Tremblay
+ */
+public final class ReflectionUtils {
+
+    private static Map<Class<?>, Class<?>> primitiveToWrapperType = new HashMap<Class<?>, Class<?>>();
+
+    static {
+        primitiveToWrapperType.put(boolean.class, Boolean.class);
+        primitiveToWrapperType.put(byte.class, Byte.class);
+        primitiveToWrapperType.put(short.class, Short.class);
+        primitiveToWrapperType.put(char.class, Character.class);
+        primitiveToWrapperType.put(int.class, Integer.class);
+        primitiveToWrapperType.put(long.class, Long.class);
+        primitiveToWrapperType.put(float.class, Float.class);
+        primitiveToWrapperType.put(double.class, Double.class);
+    }
+
+    public static final Method OBJECT_EQUALS = getDeclaredMethod(Object.class, "equals",
+            new Class[] { Object.class });
+
+    public static final Method OBJECT_HASHCODE = getDeclaredMethod(Object.class, "hashCode", (Class[]) null);
+
+    public static final Method OBJECT_TOSTRING = getDeclaredMethod(Object.class, "toString", (Class[]) null);
+
+    public static final Method OBJECT_FINALIZE = getDeclaredMethod(Object.class, "finalize", (Class[]) null);
+
+    // ///CLOVER:OFF
+    private ReflectionUtils() {
+    }
+
+    // ///CLOVER:ON
+
+    /**
+     * Attempt to find a {@link Method} on the supplied class with the supplied
+     * name and no parameters. Searches all superclasses up to
+     * <code>Object</code>.
+     * <p>
+     * Returns <code>null</code> if no {@link Method} can be found.
+     * 
+     * @param clazz
+     *            the class to introspect
+     * @param name
+     *            the name of the method
+     * @return the Method object, or <code>null</code> if none found
+     */
+    public static Method findMethod(final Class<?> clazz, final String name) {
+        return findMethod(clazz, name, (Class<?>[]) null);
+    }
+
+    /**
+     * Attempt to find a {@link Method} on the supplied class with the supplied
+     * name and parameter types. Searches all superclasses up to
+     * <code>Object</code>.
+     * <p>
+     * Returns <code>null</code> if no {@link Method} can be found.
+     * 
+     * @param clazz
+     *            the class to introspect
+     * @param name
+     *            the name of the method
+     * @param paramTypes
+     *            the parameter types of the method (may be <code>null</code> to
+     *            indicate any signature)
+     * @return the Method object, or <code>null</code> if none found
+     */
+    public static Method findMethod(final Class<?> clazz, final String name, final Class<?>... paramTypes) {
+        Class<?> searchType = clazz;
+        while (searchType != null) {
+            final Method[] methods = searchType.getDeclaredMethods();
+            Method result = null;
+            for (final Method method : methods) {
+                // Private methods can't be mocked so just skip them
+                if (Modifier.isPrivate(method.getModifiers())) {
+                    continue;
+                }
+                // Skip bridges because we never mock them. We mock the method underneath
+                if (method.isBridge()) {
+                    continue;
+                }
+                if (name.equals(method.getName())) {
+                    if (paramTypes == null) {
+                        if (result != null) {
+                            throw new RuntimeException("Ambiguous name: More than one method are named "
+                                    + name);
+                        }
+                        result = method;
+                    } else if (Arrays.equals(paramTypes, method.getParameterTypes())) {
+                        return method;
+                    }
+                }
+            }
+            if (result != null) {
+                return result;
+            }
+            searchType = searchType.getSuperclass();
+        }
+        return null;
+    }
+
+    /**
+     * Returns a constructor that contains {@code objs} as arguments.
+     * 
+     * <p>
+     * We could not do something like {@code clazz.getConstructor(objs.class())}
+     * because that would require casting all the passed arguments to the exact
+     * parameter types of the desired constructor.
+     * 
+     * @param clazz
+     *            class on which we are searching the constructor
+     * @param <T>
+     *            type of the class searched
+     * @param objs
+     *            list of arguments of the constructor
+     * @return a constructor with the arguments in {@code objs}
+     * @throws NoSuchMethodException
+     *             when the constructor with {@code args} does not exist or is
+     *             ambiguous
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Constructor<T> getConstructor(final Class<T> clazz, final Object... objs)
+            throws NoSuchMethodException {
+        Constructor<T> ret = null;
+        for (final Constructor<?> classConstructor : clazz.getDeclaredConstructors()) {
+            if (isMatchingConstructor(classConstructor, objs)) {
+                if (ret != null) {
+                    // We had already found a constructor, so this is ambiguous
+                    throw new IllegalArgumentException("Ambiguity in the constructors for " + clazz.getName()
+                            + ".");
+                }
+
+                // This unsafe cast is guaranteed to be correct by Class#getConstructors()
+                ret = (Constructor<T>) classConstructor;
+            }
+        }
+
+        if (ret != null) {
+            return ret;
+        }
+
+        // Not found
+        throw new NoSuchMethodException("Couldn't find constructor for class " + clazz.getName());
+    }
+
+    /**
+     * Returns true if objects in {@code objs} are eligible to be passed to
+     * {@code classConstructor}.
+     */
+    private static boolean isMatchingConstructor(final Constructor<?> classConstructor, final Object... objs) {
+
+        if (Modifier.isPrivate(classConstructor.getModifiers())) {
+            return false;
+        }
+
+        final Class<?>[] parameterTypes = classConstructor.getParameterTypes();
+        if (parameterTypes.length != objs.length) {
+            return false;
+        }
+
+        for (int i = 0; i < objs.length; ++i) {
+            Class<?> parameterType = parameterTypes[i];
+
+            // If the parameter is a primitive, we need to get the boxed equivalent type
+            if (parameterType.isPrimitive()) {
+                parameterType = wrapPrimitive(parameterType);
+            }
+
+            // Check if parameter type matches
+            if (!parameterType.isInstance(objs[i])) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Given a primitive type, returns its boxed equivalent. For instance, given
+     * {@code int}, returns {@code Integer}.
+     * 
+     * @param parameterType
+     *            the primitive type
+     * @return the boxed equivalent
+     */
+    private static Class<?> wrapPrimitive(final Class<?> parameterType) {
+        return primitiveToWrapperType.get(parameterType);
+    }
+
+    /**
+     * Basically calls getDeclaredMethod on a Class but wraps the
+     * NoSuchMethodException into a Runtime.
+     * 
+     * @param clazz
+     *            class on which the getDeclaredMethod is called
+     * @param name
+     *            method name
+     * @param paramTypes
+     *            method parameters
+     * @return the method searched
+     */
+    public static Method getDeclaredMethod(final Class<?> clazz, final String name,
+            final Class<?>[] paramTypes) {
+        try {
+            return clazz.getDeclaredMethod(name, paramTypes);
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/src/org/easymock/internal/ReplayState.java b/src/org/easymock/internal/ReplayState.java
index d20477f..e073d48 100644
--- a/src/org/easymock/internal/ReplayState.java
+++ b/src/org/easymock/internal/ReplayState.java
@@ -1,132 +1,156 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-
-import org.easymock.IAnswer;
-
-public class ReplayState implements IMocksControlState, Serializable {
-
-    private static final long serialVersionUID = 6314142602251047572L;
-
-    private IMocksBehavior behavior;
-
-    public ReplayState(IMocksBehavior behavior) {
-        this.behavior = behavior;
-    }
-
-    public Object invoke(Invocation invocation) throws Throwable {
-
-        if (behavior.isThreadSafe()) {
-            // If thread safe, synchronize the mock
-            synchronized (this) {
-                return invokeInner(invocation);
-            }
-        }
-
-        // Check that the same thread is called all the time...
-        behavior.checkCurrentThreadSameAsLastThread();
-        return invokeInner(invocation);
-    }
-
-    private Object invokeInner(Invocation invocation) throws Throwable {
-        Result result = behavior.addActual(invocation);
-        LastControl.pushCurrentArguments(invocation.getArguments());
-        try {
-            try {
-                return result.answer();
-            } catch (Throwable t) {
-                throw new ThrowableWrapper(t);
-            }
-        } finally {
-            LastControl.popCurrentArguments();
-        }
-    }
-
-    public void verify() {
-        behavior.verify();
-    }
-
-    public void replay() {
-        throwWrappedIllegalStateException();
-    }
-
-    public void callback(Runnable runnable) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void checkOrder(boolean value) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void makeThreadSafe(boolean threadSafe) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void andReturn(Object value) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void andThrow(Throwable throwable) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void andAnswer(IAnswer<?> answer) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void andStubReturn(Object value) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void andStubThrow(Throwable throwable) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void andStubAnswer(IAnswer<?> answer) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void asStub() {
-        throwWrappedIllegalStateException();
-    }
-
-    public void times(Range range) {
-        throwWrappedIllegalStateException();
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setMatcher(Method method, org.easymock.ArgumentsMatcher matcher) {
-        throwWrappedIllegalStateException();
-    }
-
-    @SuppressWarnings("deprecation")
-    public void setDefaultMatcher(org.easymock.ArgumentsMatcher matcher) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void setDefaultReturnValue(Object value) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void setDefaultThrowable(Throwable throwable) {
-        throwWrappedIllegalStateException();
-    }
-
-    public void setDefaultVoidCallable() {
-        throwWrappedIllegalStateException();
-    }
-
-    private void throwWrappedIllegalStateException() {
-        throw new RuntimeExceptionWrapper(new IllegalStateException(
-                "This method must not be called in replay state."));
-    }
-
-    public void assertRecordState() {
-        throwWrappedIllegalStateException();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.easymock.IAnswer;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ReplayState implements IMocksControlState, Serializable {
+
+    private static final long serialVersionUID = 6314142602251047572L;
+
+    private final IMocksBehavior behavior;
+
+    private final ReentrantLock lock = new ReentrantLock();
+
+    public ReplayState(final IMocksBehavior behavior) {
+        this.behavior = behavior;
+    }
+
+    public Object invoke(final Invocation invocation) throws Throwable {
+
+        behavior.checkThreadSafety();
+
+        if (behavior.isThreadSafe()) {
+            // If thread safe, synchronize the mock
+            lock.lock();
+            try {
+                return invokeInner(invocation);
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        return invokeInner(invocation);
+    }
+
+    private Object invokeInner(final Invocation invocation) throws Throwable {
+        LastControl.pushCurrentInvocation(invocation);
+        try {
+            final Result result = behavior.addActual(invocation);
+            try {
+                return result.answer();
+            } catch (final Throwable t) {
+                if (result.shouldFillInStackTrace()) {
+                    throw new ThrowableWrapper(t);
+                }
+                throw t;
+            }
+        } finally {
+            LastControl.popCurrentInvocation();
+        }
+    }
+
+    public void verify() {
+        behavior.verify();
+    }
+
+    public void replay() {
+        throwWrappedIllegalStateException();
+    }
+
+    public void callback(final Runnable runnable) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void checkOrder(final boolean value) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void makeThreadSafe(final boolean threadSafe) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void checkIsUsedInOneThread(final boolean shouldBeUsedInOneThread) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andReturn(final Object value) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andThrow(final Throwable throwable) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andAnswer(final IAnswer<?> answer) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andDelegateTo(final Object answer) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andStubReturn(final Object value) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andStubThrow(final Throwable throwable) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andStubAnswer(final IAnswer<?> answer) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void andStubDelegateTo(final Object delegateTo) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void asStub() {
+        throwWrappedIllegalStateException();
+    }
+
+    public void times(final Range range) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void setDefaultReturnValue(final Object value) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void setDefaultThrowable(final Throwable throwable) {
+        throwWrappedIllegalStateException();
+    }
+
+    public void setDefaultVoidCallable() {
+        throwWrappedIllegalStateException();
+    }
+
+    private void throwWrappedIllegalStateException() {
+        throw new RuntimeExceptionWrapper(new IllegalStateException(
+                "This method must not be called in replay state."));
+    }
+
+    public void assertRecordState() {
+        throwWrappedIllegalStateException();
+    }
+}
diff --git a/src/org/easymock/internal/Result.java b/src/org/easymock/internal/Result.java
index 394096d..4c82b2d 100644
--- a/src/org/easymock/internal/Result.java
+++ b/src/org/easymock/internal/Result.java
@@ -1,69 +1,117 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-
-import org.easymock.IAnswer;
-
-public class Result implements IAnswer<Object>, Serializable {
-
-    private static final long serialVersionUID = 5476251941213917681L;
-    
-    private IAnswer<?> value;
-
-    private Result(IAnswer<?> value) {
-        this.value = value;
-    }
-
-    public static Result createThrowResult(final Throwable throwable) {
-        class ThrowingAnswer implements IAnswer<Object>, Serializable {
-
-            private static final long serialVersionUID = -332797751209289222L;
-
-            public Object answer() throws Throwable {
-                throw throwable;
-            }
-
-            @Override
-            public String toString() {
-                return "Answer throwing " + throwable;
-            }
-        }
-        return new Result(new ThrowingAnswer());
-    }
-
-    public static Result createReturnResult(final Object value) {
-        class ReturningAnswer implements IAnswer<Object>, Serializable {
-
-            private static final long serialVersionUID = 6973893913593916866L;
-            
-            public Object answer() throws Throwable {
-                return value;
-            }
-            
-            @Override
-            public String toString() {
-                return "Answer returning " + value;
-            }
-        }
-        return new Result(new ReturningAnswer());
-    }
-
-    public static Result createAnswerResult(IAnswer<?> answer) {
-        return new Result(answer);
-    }
-
-    public Object answer() throws Throwable {
-        return value.answer();
-    }
-
-    @Override
-    public String toString() {
-        return value.toString();
-    }
-    
-    
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.easymock.IAnswer;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public final class Result implements IAnswer<Object>, Serializable {
+
+    private static final long serialVersionUID = 5476251941213917681L;
+
+    private final IAnswer<?> value;
+
+    private final boolean shouldFillInStackTrace;
+
+    private Result(final IAnswer<?> value, final boolean shouldFillInStackTrace) {
+        this.value = value;
+        this.shouldFillInStackTrace = shouldFillInStackTrace;
+    }
+
+    public static Result createThrowResult(final Throwable throwable) {
+        class ThrowingAnswer implements IAnswer<Object>, Serializable {
+
+            private static final long serialVersionUID = -332797751209289222L;
+
+            public Object answer() throws Throwable {
+                throw throwable;
+            }
+
+            @Override
+            public String toString() {
+                return "Answer throwing " + throwable;
+            }
+        }
+        return new Result(new ThrowingAnswer(), true);
+    }
+
+    public static Result createReturnResult(final Object value) {
+        class ReturningAnswer implements IAnswer<Object>, Serializable {
+
+            private static final long serialVersionUID = 6973893913593916866L;
+
+            public Object answer() throws Throwable {
+                return value;
+            }
+
+            @Override
+            public String toString() {
+                return "Answer returning " + value;
+            }
+        }
+        return new Result(new ReturningAnswer(), true);
+    }
+
+    public static Result createDelegatingResult(final Object value) {
+        class DelegatingAnswer implements IAnswer<Object>, Serializable {
+
+            private static final long serialVersionUID = -5699326678580460103L;
+
+            public Object answer() throws Throwable {
+                final Invocation invocation = LastControl.getCurrentInvocation();
+                try {
+                    final Method m = invocation.getMethod();
+                    m.setAccessible(true);
+                    return m.invoke(value, invocation.getArguments());
+                } catch (final IllegalArgumentException e) {
+                    throw new IllegalArgumentException("Delegation to object [" + value
+                            + "] is not implementing the mocked method [" + invocation.getMethod() + "]", e);
+                } catch (final InvocationTargetException e) {
+                    throw e.getCause();
+                }
+            }
+
+            @Override
+            public String toString() {
+                return "Delegated to " + value;
+            }
+        }
+        return new Result(new DelegatingAnswer(), false);
+    }
+
+    public static Result createAnswerResult(final IAnswer<?> answer) {
+        return new Result(answer, false);
+    }
+
+    public Object answer() throws Throwable {
+        return value.answer();
+    }
+
+    public boolean shouldFillInStackTrace() {
+        return shouldFillInStackTrace;
+    }
+
+    @Override
+    public String toString() {
+        return value.toString();
+    }
+}
diff --git a/src/org/easymock/internal/Results.java b/src/org/easymock/internal/Results.java
index 567c04e..d560c15 100644
--- a/src/org/easymock/internal/Results.java
+++ b/src/org/easymock/internal/Results.java
@@ -1,78 +1,107 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-public class Results implements Serializable {
-
-    private static final long serialVersionUID = -2722051869610289637L;
-
-    private int callCount;
-
-    private LinkedList<Range> ranges = new LinkedList<Range>();
-
-    private List<Result> results = new ArrayList<Result>();
-
-    public void add(Result result, Range range) {
-        if (!ranges.isEmpty()) {
-            Range lastRange = ranges.getLast();
-            if (!lastRange.hasFixedCount())
-                throw new RuntimeExceptionWrapper(
-                        new IllegalStateException(
-                                "last method called on mock already has a non-fixed count set."));
-        }
-        ranges.add(range);
-        results.add(result);
-    }
-
-    public Result next() {
-        int currentPosition = 0;
-        for (int i = 0; i < ranges.size(); i++) {
-            Range interval = ranges.get(i);
-            if (interval.hasOpenCount()) {
-                callCount += 1;
-                return results.get(i);
-            }
-            currentPosition += interval.getMaximum();
-            if (currentPosition > callCount) {
-                callCount += 1;
-                return results.get(i);
-            }
-        }
-        return null;
-    }
-
-    public boolean hasValidCallCount() {
-        return getMainInterval().contains(getCallCount());
-    }
-
-    @Override
-    public String toString() {
-        return getMainInterval().expectedAndActual(getCallCount());
-    }
-
-    private Range getMainInterval() {
-        int min = 0, max = 0;
-
-        for (Range interval : ranges) {
-            min += interval.getMinimum();
-            if (interval.hasOpenCount() || max == Integer.MAX_VALUE) {
-                max = Integer.MAX_VALUE;
-            } else {
-                max += interval.getMaximum();
-            }
-        }
-
-        return new Range(min, max);
-    }
-
-    public int getCallCount() {
-        return callCount;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Results implements Serializable {
+
+    private static final long serialVersionUID = -2722051869610289637L;
+
+    private int callCount;
+
+    private final LinkedList<Range> ranges = new LinkedList<Range>();
+
+    private final List<Result> results = new ArrayList<Result>();
+
+    public void add(final Result result, final Range range) {
+        if (!ranges.isEmpty()) {
+            final Range lastRange = ranges.getLast();
+            if (!lastRange.hasFixedCount()) {
+                throw new RuntimeExceptionWrapper(new IllegalStateException(
+                        "last method called on mock already has a non-fixed count set."));
+            }
+        }
+        ranges.add(range);
+        results.add(result);
+    }
+
+    public boolean hasResults() {
+        int currentPosition = 0;
+        for (int i = 0; i < ranges.size(); i++) {
+            final Range interval = ranges.get(i);
+            if (interval.hasOpenCount()) {
+                return true;
+            }
+            currentPosition += interval.getMaximum();
+            if (currentPosition > callCount) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Result next() {
+        int currentPosition = 0;
+        for (int i = 0; i < ranges.size(); i++) {
+            final Range interval = ranges.get(i);
+            if (interval.hasOpenCount()) {
+                callCount += 1;
+                return results.get(i);
+            }
+            currentPosition += interval.getMaximum();
+            if (currentPosition > callCount) {
+                callCount += 1;
+                return results.get(i);
+            }
+        }
+        return null;
+    }
+
+    public boolean hasValidCallCount() {
+        return getMainInterval().contains(getCallCount());
+    }
+
+    @Override
+    public String toString() {
+        return getMainInterval().expectedCount();
+    }
+
+    private Range getMainInterval() {
+        int min = 0, max = 0;
+
+        for (final Range interval : ranges) {
+            min += interval.getMinimum();
+            if (interval.hasOpenCount() || max == Integer.MAX_VALUE) {
+                max = Integer.MAX_VALUE;
+            } else {
+                max += interval.getMaximum();
+            }
+        }
+
+        return new Range(min, max);
+    }
+
+    public int getCallCount() {
+        return callCount;
+    }
+}
diff --git a/src/org/easymock/internal/RuntimeExceptionWrapper.java b/src/org/easymock/internal/RuntimeExceptionWrapper.java
index 99e883b..a5e1e3e 100644
--- a/src/org/easymock/internal/RuntimeExceptionWrapper.java
+++ b/src/org/easymock/internal/RuntimeExceptionWrapper.java
@@ -1,20 +1,34 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-public class RuntimeExceptionWrapper extends RuntimeException {
-
-    private static final long serialVersionUID = -3483500330975410177L;
-    
-    private final RuntimeException runtimeException;
-
-    public RuntimeExceptionWrapper(final RuntimeException runtimeException) {
-        this.runtimeException = runtimeException;
-    }
-
-    public RuntimeException getRuntimeException() {
-        return runtimeException;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RuntimeExceptionWrapper extends RuntimeException {
+
+    private static final long serialVersionUID = -3483500330975410177L;
+
+    private final RuntimeException runtimeException;
+
+    public RuntimeExceptionWrapper(final RuntimeException runtimeException) {
+        this.runtimeException = runtimeException;
+    }
+
+    public RuntimeException getRuntimeException() {
+        return runtimeException;
+    }
+}
diff --git a/src/org/easymock/internal/ThrowableWrapper.java b/src/org/easymock/internal/ThrowableWrapper.java
index 0f82617..35f9aa0 100644
--- a/src/org/easymock/internal/ThrowableWrapper.java
+++ b/src/org/easymock/internal/ThrowableWrapper.java
@@ -1,20 +1,34 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-public class ThrowableWrapper extends Throwable {
-
-    private static final long serialVersionUID = -4434322855124959723L;
-    
-    private final Throwable throwable;
-
-    public ThrowableWrapper(final Throwable throwable) {
-        this.throwable = throwable;
-    }
-
-    public Throwable getThrowable() {
-        return throwable;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ThrowableWrapper extends Throwable {
+
+    private static final long serialVersionUID = -4434322855124959723L;
+
+    private final Throwable throwable;
+
+    public ThrowableWrapper(final Throwable throwable) {
+        this.throwable = throwable;
+    }
+
+    public Throwable getThrowable() {
+        return throwable;
+    }
+}
diff --git a/src/org/easymock/internal/UnorderedBehavior.java b/src/org/easymock/internal/UnorderedBehavior.java
index 2144c20..0dc161e 100644
--- a/src/org/easymock/internal/UnorderedBehavior.java
+++ b/src/org/easymock/internal/UnorderedBehavior.java
@@ -1,95 +1,112 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-public class UnorderedBehavior implements Serializable {
-
-    private static final long serialVersionUID = 2185791334636597469L;
-
-    private final List<ExpectedInvocationAndResults> results = new ArrayList<ExpectedInvocationAndResults>();
-
-    private final boolean checkOrder;
-
-    public UnorderedBehavior(boolean checkOrder) {
-        this.checkOrder = checkOrder;
-    }
-
-    public void addExpected(ExpectedInvocation expected, Result result,
-            Range count) {
-        for (ExpectedInvocationAndResults entry : results) {
-            if (entry.getExpectedInvocation().equals(expected)) {
-                entry.getResults().add(result, count);
-                return;
-            }
-        }
-        Results list = new Results();
-        list.add(result, count);
-        results.add(new ExpectedInvocationAndResults(expected, list));
-    }
-
-    public Result addActual(Invocation actual) {
-        for (ExpectedInvocationAndResults entry : results) {
-            if (!entry.getExpectedInvocation().matches(actual)) {
-                continue;
-            }
-            Result result = entry.getResults().next();
-            if (result != null) {
-                return result;
-            }
-        }
-        return null;
-    }
-
-    public boolean verify() {
-        for (ExpectedInvocationAndResults entry : results) {
-            if (!entry.getResults().hasValidCallCount()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return toString(null);
-    }
-
-    public String toString(Invocation invocation) {
-        StringBuffer result = new StringBuffer();
-        for (ExpectedInvocationAndResults entry : results) {
-            boolean unordered = !checkOrder;
-            boolean validCallCount = entry.getResults().hasValidCallCount();
-            boolean match = invocation != null
-                    && entry.getExpectedInvocation().matches(invocation);
-
-            if (unordered && validCallCount && !match) {
-                continue;
-            }
-            result.append("\n    " + entry.toString());
-            if (match) {
-                result.append(" (+1)");
-            }
-        }
-        return result.toString();
-    }
-
-    public boolean allowsExpectedInvocation(ExpectedInvocation expected,
-            boolean checkOrder) {
-        if (this.checkOrder != checkOrder) {
-            return false;
-        } else if (results.isEmpty() || !this.checkOrder) {
-            return true;
-        } else {
-            ExpectedInvocation lastMethodCall = results.get(results.size() - 1)
-                    .getExpectedInvocation();
-            return lastMethodCall.equals(expected);
-        }
-    }
-
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UnorderedBehavior implements Serializable {
+
+    private static final long serialVersionUID = 2185791334636597469L;
+
+    private final List<ExpectedInvocationAndResults> results = new ArrayList<ExpectedInvocationAndResults>();
+
+    private final boolean checkOrder;
+
+    public UnorderedBehavior(final boolean checkOrder) {
+        this.checkOrder = checkOrder;
+    }
+
+    public void addExpected(final ExpectedInvocation expected, final Result result, final Range count) {
+        for (final ExpectedInvocationAndResults entry : results) {
+            if (entry.getExpectedInvocation().equals(expected)) {
+                entry.getResults().add(result, count);
+                return;
+            }
+        }
+        final Results list = new Results();
+        list.add(result, count);
+        results.add(new ExpectedInvocationAndResults(expected, list));
+    }
+
+    public Result addActual(final Invocation actual) {
+        for (final ExpectedInvocationAndResults entry : results) {
+            try {
+                // if no results are available anymore, it's worthless to try to match
+                if (!entry.getResults().hasResults()) {
+                    continue;
+                }
+                // if it doesn't match, keep searching
+                if (!entry.getExpectedInvocation().matches(actual)) {
+                    continue;
+                }
+                final Result result = entry.getResults().next();
+                // actual and expected matched, validate the capture
+                actual.validateCaptures();
+                return result;
+            } finally {
+                // reset the capture (already validated or expected didn't
+                // matched)
+                actual.clearCaptures();
+            }
+        }
+        return null;
+    }
+
+    public boolean verify() {
+        for (final ExpectedInvocationAndResults entry : results) {
+            if (!entry.getResults().hasValidCallCount()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public List<ErrorMessage> getMessages(final Invocation invocation) {
+        final List<ErrorMessage> messages = new ArrayList<ErrorMessage>(results.size());
+        for (final ExpectedInvocationAndResults entry : results) {
+            final boolean unordered = !checkOrder;
+            final boolean validCallCount = entry.getResults().hasValidCallCount();
+            final boolean match = invocation != null && entry.getExpectedInvocation().matches(invocation);
+
+            if (unordered && validCallCount && !match) {
+                continue;
+            }
+
+            final ErrorMessage message = new ErrorMessage(match, entry.toString(), entry.getResults()
+                    .getCallCount());
+            messages.add(message);
+        }
+        return messages;
+
+    }
+
+    public boolean allowsExpectedInvocation(final ExpectedInvocation expected, final boolean checkOrder) {
+        if (this.checkOrder != checkOrder) {
+            return false;
+        } else if (results.isEmpty() || !this.checkOrder) {
+            return true;
+        } else {
+            final ExpectedInvocation lastMethodCall = results.get(results.size() - 1).getExpectedInvocation();
+            return lastMethodCall.equals(expected);
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/src/org/easymock/internal/matchers/And.java b/src/org/easymock/internal/matchers/And.java
index 8871acf..3c3788e 100644
--- a/src/org/easymock/internal/matchers/And.java
+++ b/src/org/easymock/internal/matchers/And.java
@@ -1,42 +1,56 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-
-import org.easymock.IArgumentMatcher;
-
-public class And implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = 3874580646798403818L;
-    
-    private final List<IArgumentMatcher> matchers;
-
-    public And(List<IArgumentMatcher> matchers) {
-        this.matchers = matchers;
-    }
-
-    public boolean matches(Object actual) {
-        for (IArgumentMatcher matcher : matchers) {
-            if (!matcher.matches(actual)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("and(");
-        for (Iterator<IArgumentMatcher> it = matchers.iterator(); it.hasNext();) {
-            it.next().appendTo(buffer);
-            if (it.hasNext()) {
-                buffer.append(", ");
-            }
-        }
-        buffer.append(")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class And implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = 3874580646798403818L;
+
+    private final List<IArgumentMatcher> matchers;
+
+    public And(final List<IArgumentMatcher> matchers) {
+        this.matchers = matchers;
+    }
+
+    public boolean matches(final Object actual) {
+        for (final IArgumentMatcher matcher : matchers) {
+            if (!matcher.matches(actual)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("and(");
+        for (final Iterator<IArgumentMatcher> it = matchers.iterator(); it.hasNext();) {
+            it.next().appendTo(buffer);
+            if (it.hasNext()) {
+                buffer.append(", ");
+            }
+        }
+        buffer.append(")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Any.java b/src/org/easymock/internal/matchers/Any.java
index 1a21d29..192ded5 100644
--- a/src/org/easymock/internal/matchers/Any.java
+++ b/src/org/easymock/internal/matchers/Any.java
@@ -1,28 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Any implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -3743894206806704049L;
-    
-    public static final Any ANY = new Any();    
-    
-    private Any() {
-        
-    }
-    
-    public boolean matches(Object actual) {
-        return true;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("<any>");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public final class Any implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -3743894206806704049L;
+
+    public static final Any ANY = new Any();
+
+    private Any() {
+
+    }
+
+    public boolean matches(final Object actual) {
+        return true;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("<any>");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/ArrayEquals.java b/src/org/easymock/internal/matchers/ArrayEquals.java
index 24bb88f..1c77a43 100644
--- a/src/org/easymock/internal/matchers/ArrayEquals.java
+++ b/src/org/easymock/internal/matchers/ArrayEquals.java
@@ -1,81 +1,63 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.lang.reflect.Array;
-import java.util.Arrays;
-
-public class ArrayEquals extends Equals {
-
-    private static final long serialVersionUID = 1L;
-
-    public ArrayEquals(Object expected) {
-        super(expected);
-    }
-
-    public boolean matches(Object actual) {
-        Object expected = getExpected();
-        if (expected instanceof boolean[]
-                && (actual == null || actual instanceof boolean[])) {
-            return Arrays.equals((boolean[]) expected, (boolean[]) actual);
-        } else if (expected instanceof byte[]
-                && (actual == null || actual instanceof byte[])) {
-            return Arrays.equals((byte[]) expected, (byte[]) actual);
-        } else if (expected instanceof char[]
-                && (actual == null || actual instanceof char[])) {
-            return Arrays.equals((char[]) expected, (char[]) actual);
-        } else if (expected instanceof double[]
-                && (actual == null || actual instanceof double[])) {
-            return Arrays.equals((double[]) expected, (double[]) actual);
-        } else if (expected instanceof float[]
-                && (actual == null || actual instanceof float[])) {
-            return Arrays.equals((float[]) expected, (float[]) actual);
-        } else if (expected instanceof int[]
-                && (actual == null || actual instanceof int[])) {
-            return Arrays.equals((int[]) expected, (int[]) actual);
-        } else if (expected instanceof long[]
-                && (actual == null || actual instanceof long[])) {
-            return Arrays.equals((long[]) expected, (long[]) actual);
-        } else if (expected instanceof short[]
-                && (actual == null || actual instanceof short[])) {
-            return Arrays.equals((short[]) expected, (short[]) actual);
-        } else if (expected instanceof Object[]
-                && (actual == null || actual instanceof Object[])) {
-            return Arrays.equals((Object[]) expected, (Object[]) actual);
-        } else {
-            return super.matches(actual);
-        }
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        if (getExpected() != null && getExpected().getClass().isArray()) {
-            appendArray(createObjectArray(getExpected()), buffer);
-        } else {
-            super.appendTo(buffer);
-        }
-    }
-
-    private void appendArray(Object[] array, StringBuffer buffer) {
-        buffer.append("[");
-        for (int i = 0; i < array.length; i++) {
-            new Equals(array[i]).appendTo(buffer);
-            if (i != array.length - 1) {
-                buffer.append(", ");
-            }
-        }
-        buffer.append("]");
-    }
-
-    public static Object[] createObjectArray(Object array) {
-        if (array instanceof Object[]) {
-            return (Object[]) array;
-        }
-        Object[] result = new Object[Array.getLength(array)];
-        for (int i = 0; i < Array.getLength(array); i++) {
-            result[i] = Array.get(array, i);
-        }
-        return result;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.util.Arrays;
+
+import org.easymock.internal.ArgumentToString;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ArrayEquals extends Equals {
+
+    private static final long serialVersionUID = 1L;
+
+    public ArrayEquals(final Object expected) {
+        super(expected);
+    }
+
+    @Override
+    public boolean matches(final Object actual) {
+        final Object expected = getExpected();
+        if (expected instanceof boolean[] && (actual == null || actual instanceof boolean[])) {
+            return Arrays.equals((boolean[]) expected, (boolean[]) actual);
+        } else if (expected instanceof byte[] && (actual == null || actual instanceof byte[])) {
+            return Arrays.equals((byte[]) expected, (byte[]) actual);
+        } else if (expected instanceof char[] && (actual == null || actual instanceof char[])) {
+            return Arrays.equals((char[]) expected, (char[]) actual);
+        } else if (expected instanceof double[] && (actual == null || actual instanceof double[])) {
+            return Arrays.equals((double[]) expected, (double[]) actual);
+        } else if (expected instanceof float[] && (actual == null || actual instanceof float[])) {
+            return Arrays.equals((float[]) expected, (float[]) actual);
+        } else if (expected instanceof int[] && (actual == null || actual instanceof int[])) {
+            return Arrays.equals((int[]) expected, (int[]) actual);
+        } else if (expected instanceof long[] && (actual == null || actual instanceof long[])) {
+            return Arrays.equals((long[]) expected, (long[]) actual);
+        } else if (expected instanceof short[] && (actual == null || actual instanceof short[])) {
+            return Arrays.equals((short[]) expected, (short[]) actual);
+        } else if (expected instanceof Object[] && (actual == null || actual instanceof Object[])) {
+            return Arrays.equals((Object[]) expected, (Object[]) actual);
+        } else {
+            return super.matches(actual);
+        }
+    }
+
+    @Override
+    public void appendTo(final StringBuffer buffer) {
+        ArgumentToString.appendArgument(getExpected(), buffer);
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Captures.java b/src/org/easymock/internal/matchers/Captures.java
index 116a630..3716654 100644
--- a/src/org/easymock/internal/matchers/Captures.java
+++ b/src/org/easymock/internal/matchers/Captures.java
@@ -1,31 +1,59 @@
-/*
- * Copyright (c) 2003-2008 OFFIS, Henri Tremblay. 
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.Capture;
-import org.easymock.IArgumentMatcher;
-
-public class Captures<T> implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = 5370646694100653250L;
-    
-    private Capture<T> capture;
-
-    public Captures(Capture<T> captured) {
-        this.capture = captured;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("capture(").append(capture).append(")");
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean matches(Object actual) {
-        capture.setValue((T) actual);
-        return true;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.Capture;
+import org.easymock.IArgumentMatcher;
+import org.easymock.internal.LastControl;
+
+/**
+ * @param <T>
+ *            Type of the value captured
+ * 
+ * @author Henri Tremblay
+ */
+public class Captures<T> implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -5048595127450771363L;
+
+    private final Capture<T> capture;
+
+    private T potentialValue;
+
+    public Captures(final Capture<T> captured) {
+        this.capture = captured;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("capture(").append(capture).append(")");
+    }
+
+    public void setPotentialValue(final T potentialValue) {
+        this.potentialValue = potentialValue;
+    }
+
+    @SuppressWarnings("unchecked")
+    public boolean matches(final Object actual) {
+        LastControl.getCurrentInvocation().addCapture((Captures<Object>) this, actual);
+        return true;
+    }
+
+    public void validateCapture() {
+        capture.setValue(potentialValue);
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Compare.java b/src/org/easymock/internal/matchers/Compare.java
index 98045ff..1bb6974 100644
--- a/src/org/easymock/internal/matchers/Compare.java
+++ b/src/org/easymock/internal/matchers/Compare.java
@@ -1,42 +1,58 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Henri Tremblay.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-import java.util.Comparator;
-
-import org.easymock.IArgumentMatcher;
-import org.easymock.LogicalOperator;
-
-public class Compare<T> implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -4859402739599754147L;
-
-    private T expected;
-
-    private Comparator<? super T> comparator;
-
-    private LogicalOperator operator;
-
-    public Compare(T expected, Comparator<? super T> comparator, LogicalOperator result) {
-        this.expected = expected;
-        this.comparator = comparator;
-        this.operator = result;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append(comparator + "(" + expected + ") " + operator.getSymbol()
-                + " 0");
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean matches(Object actual) {
-        if(actual == null) {
-            return false;
-        }
-        return operator.matchResult(comparator.compare((T) actual, expected));
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.easymock.IArgumentMatcher;
+import org.easymock.LogicalOperator;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author Henri Tremblay
+ */
+public class Compare<T> implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -4859402739599754147L;
+
+    private final T expected;
+
+    private final Comparator<? super T> comparator;
+
+    private final LogicalOperator operator;
+
+    public Compare(final T expected, final Comparator<? super T> comparator, final LogicalOperator result) {
+        this.expected = expected;
+        this.comparator = comparator;
+        this.operator = result;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append(comparator + "(" + expected + ") " + operator.getSymbol() + " 0");
+    }
+
+    @SuppressWarnings("unchecked")
+    public boolean matches(final Object actual) {
+        if (actual == null) {
+            return false;
+        }
+        return operator.matchResult(comparator.compare((T) actual, expected));
+    }
+
+}
diff --git a/src/org/easymock/internal/matchers/CompareEqual.java b/src/org/easymock/internal/matchers/CompareEqual.java
index 1f26e83..79fefc2 100644
--- a/src/org/easymock/internal/matchers/CompareEqual.java
+++ b/src/org/easymock/internal/matchers/CompareEqual.java
@@ -1,24 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-public class CompareEqual<T extends Comparable<T>> extends CompareTo<T> {
-
-    private static final long serialVersionUID = 7616033998227799268L;
-
-    public CompareEqual(Comparable<T> value) {
-        super(value);
-    }
-
-    @Override
-    protected String getName() {
-        return "cmpEq";
-    }
-
-    @Override
-    protected boolean matchResult(int result) {
-        return result == 0;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author Henri Tremblay
+ */
+public class CompareEqual<T extends Comparable<T>> extends CompareTo<T> {
+
+    private static final long serialVersionUID = 7616033998227799268L;
+
+    public CompareEqual(final Comparable<T> value) {
+        super(value);
+    }
+
+    @Override
+    protected String getName() {
+        return "cmpEq";
+    }
+
+    @Override
+    protected boolean matchResult(final int result) {
+        return result == 0;
+    }
+}
diff --git a/src/org/easymock/internal/matchers/CompareTo.java b/src/org/easymock/internal/matchers/CompareTo.java
index bdf3e43..41b99c5 100644
--- a/src/org/easymock/internal/matchers/CompareTo.java
+++ b/src/org/easymock/internal/matchers/CompareTo.java
@@ -1,38 +1,55 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public abstract class CompareTo<T extends Comparable<T>> implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -8447010713532143168L;
-    
-    private final Comparable<T> expected;
-
-    public CompareTo(Comparable<T> value) {
-        this.expected = value;
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean matches(Object actual) {
-        
-        if(!(actual instanceof Comparable)) {
-            return false;
-        }
-        
-        return matchResult(((Comparable) actual).compareTo(expected));
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append(getName() + "(" + expected + ")");
-    }
-    
-    protected abstract String getName();
-    
-    protected abstract boolean matchResult(int result);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author Henri Tremblay
+ */
+public abstract class CompareTo<T extends Comparable<T>> implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -8447010713532143168L;
+
+    private final Comparable<T> expected;
+
+    public CompareTo(final Comparable<T> value) {
+        this.expected = value;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public boolean matches(final Object actual) {
+
+        if (!(actual instanceof Comparable)) {
+            return false;
+        }
+
+        return matchResult(((Comparable) actual).compareTo(expected));
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append(getName() + "(" + expected + ")");
+    }
+
+    protected abstract String getName();
+
+    protected abstract boolean matchResult(int result);
+}
diff --git a/src/org/easymock/internal/matchers/Contains.java b/src/org/easymock/internal/matchers/Contains.java
index 3d90860..be2ad00 100644
--- a/src/org/easymock/internal/matchers/Contains.java
+++ b/src/org/easymock/internal/matchers/Contains.java
@@ -1,29 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Contains implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -6785245714002503134L;
-
-    private final String substring;
-
-    public Contains(String substring) {
-        this.substring = substring;
-    }
-
-    public boolean matches(Object actual) {
-        return (actual instanceof String)
-                && ((String) actual).indexOf(substring) >= 0;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("contains(\"" + substring + "\")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Contains implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -6785245714002503134L;
+
+    private final String substring;
+
+    public Contains(final String substring) {
+        this.substring = substring;
+    }
+
+    public boolean matches(final Object actual) {
+        return (actual instanceof String) && ((String) actual).indexOf(substring) >= 0;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("contains(\"" + substring + "\")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/EndsWith.java b/src/org/easymock/internal/matchers/EndsWith.java
index 41a1dee..b462723 100644
--- a/src/org/easymock/internal/matchers/EndsWith.java
+++ b/src/org/easymock/internal/matchers/EndsWith.java
@@ -1,28 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class EndsWith implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = 5159338714596685067L;
-
-    private final String suffix;
-
-    public EndsWith(String suffix) {
-        this.suffix = suffix;
-    }
-
-    public boolean matches(Object actual) {
-        return (actual instanceof String) && ((String) actual).endsWith(suffix);
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("endsWith(\"" + suffix + "\")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class EndsWith implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = 5159338714596685067L;
+
+    private final String suffix;
+
+    public EndsWith(final String suffix) {
+        this.suffix = suffix;
+    }
+
+    public boolean matches(final Object actual) {
+        return (actual instanceof String) && ((String) actual).endsWith(suffix);
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("endsWith(\"" + suffix + "\")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Equals.java b/src/org/easymock/internal/matchers/Equals.java
index deed3f6..152af1b 100644
--- a/src/org/easymock/internal/matchers/Equals.java
+++ b/src/org/easymock/internal/matchers/Equals.java
@@ -1,61 +1,66 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Equals implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = 583055160049982067L;
-
-    private final Object expected;
-
-    public Equals(Object expected) {
-        this.expected = expected;
-    }
-
-    public boolean matches(Object actual) {
-        if (this.expected == null) {
-            return actual == null;
-        }
-        return expected.equals(actual);
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        appendQuoting(buffer);
-        buffer.append(expected);
-        appendQuoting(buffer);
-    }
-
-    private void appendQuoting(StringBuffer buffer) {
-        if (expected instanceof String) {
-            buffer.append("\"");
-        } else if (expected instanceof Character) {
-            buffer.append("'");
-        }
-    }
-
-    protected final Object getExpected() {
-        return expected;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == null || !this.getClass().equals(o.getClass()))
-            return false;
-        Equals other = (Equals) o;
-        return this.expected == null && other.expected == null
-                || this.expected != null
-                && this.expected.equals(other.expected);
-    }
-
-    @Override
-    public int hashCode() {
-        throw new UnsupportedOperationException("hashCode() is not supported");
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+import org.easymock.internal.ArgumentToString;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Equals implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = 583055160049982067L;
+
+    private final Object expected;
+
+    public Equals(final Object expected) {
+        this.expected = expected;
+    }
+
+    public boolean matches(final Object actual) {
+        if (this.expected == null) {
+            return actual == null;
+        }
+        return expected.equals(actual);
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        ArgumentToString.appendArgument(expected, buffer);
+    }
+
+    protected final Object getExpected() {
+        return expected;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (o == null || !this.getClass().equals(o.getClass())) {
+            return false;
+        }
+        final Equals other = (Equals) o;
+        return this.expected == null && other.expected == null || this.expected != null
+                && this.expected.equals(other.expected);
+    }
+
+    @Override
+    public int hashCode() {
+        throw new UnsupportedOperationException("hashCode() is not supported");
+    }
+
+}
diff --git a/src/org/easymock/internal/matchers/EqualsWithDelta.java b/src/org/easymock/internal/matchers/EqualsWithDelta.java
index c6fbdeb..c50e646 100644
--- a/src/org/easymock/internal/matchers/EqualsWithDelta.java
+++ b/src/org/easymock/internal/matchers/EqualsWithDelta.java
@@ -1,35 +1,47 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class EqualsWithDelta implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -3018631689416120154L;
-
-    private final Number expected;
-
-    private final Number delta;
-
-    public EqualsWithDelta(Number value, Number delta) {
-        this.expected = value;
-        this.delta = delta;
-    }
-
-    public boolean matches(Object actual) {
-        Number actualNumber = (Number) actual;
-        return expected.doubleValue() - delta.doubleValue() <= actualNumber
-                .doubleValue()
-                && actualNumber.doubleValue() <= expected.doubleValue()
-                        + delta.doubleValue();
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("eq(" + expected + ", " + delta + ")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class EqualsWithDelta implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -3018631689416120154L;
+
+    private final Number expected;
+
+    private final Number delta;
+
+    public EqualsWithDelta(final Number value, final Number delta) {
+        this.expected = value;
+        this.delta = delta;
+    }
+
+    public boolean matches(final Object actual) {
+        final Number actualNumber = (Number) actual;
+        return expected.doubleValue() - delta.doubleValue() <= actualNumber.doubleValue()
+                && actualNumber.doubleValue() <= expected.doubleValue() + delta.doubleValue();
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("eq(" + expected + ", " + delta + ")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Find.java b/src/org/easymock/internal/matchers/Find.java
index 2ed435a..9d0ba34 100644
--- a/src/org/easymock/internal/matchers/Find.java
+++ b/src/org/easymock/internal/matchers/Find.java
@@ -1,30 +1,43 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-import java.util.regex.Pattern;
-
-import org.easymock.IArgumentMatcher;
-
-public class Find implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -7104607303959381785L;
-
-    private final String regex;
-
-    public Find(String regex) {
-        this.regex = regex;
-    }
-
-    public boolean matches(Object actual) {
-        return (actual instanceof String)
-                && Pattern.compile(regex).matcher((String) actual).find();
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("find(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+import java.util.regex.Pattern;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Find implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -7104607303959381785L;
+
+    private final String regex;
+
+    public Find(final String regex) {
+        this.regex = regex;
+    }
+
+    public boolean matches(final Object actual) {
+        return (actual instanceof String) && Pattern.compile(regex).matcher((String) actual).find();
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("find(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/GreaterOrEqual.java b/src/org/easymock/internal/matchers/GreaterOrEqual.java
index 333fb3a..b77eb34 100644
--- a/src/org/easymock/internal/matchers/GreaterOrEqual.java
+++ b/src/org/easymock/internal/matchers/GreaterOrEqual.java
@@ -1,24 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-public class GreaterOrEqual<T extends Comparable<T>> extends CompareTo<T> {
-
-    private static final long serialVersionUID = -504083241204488174L;
-
-    public GreaterOrEqual(Comparable<T> value) {
-        super(value);
-    }
-
-    @Override
-    protected String getName() {
-        return "geq";
-    }
-
-    @Override
-    protected boolean matchResult(int result) {
-        return result >= 0;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public class GreaterOrEqual<T extends Comparable<T>> extends CompareTo<T> {
+
+    private static final long serialVersionUID = -504083241204488174L;
+
+    public GreaterOrEqual(final Comparable<T> value) {
+        super(value);
+    }
+
+    @Override
+    protected String getName() {
+        return "geq";
+    }
+
+    @Override
+    protected boolean matchResult(final int result) {
+        return result >= 0;
+    }
+}
diff --git a/src/org/easymock/internal/matchers/GreaterThan.java b/src/org/easymock/internal/matchers/GreaterThan.java
index a33e9d9..052cd02 100644
--- a/src/org/easymock/internal/matchers/GreaterThan.java
+++ b/src/org/easymock/internal/matchers/GreaterThan.java
@@ -1,24 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-public class GreaterThan<T extends Comparable<T>> extends CompareTo<T> {
-
-    private static final long serialVersionUID = 2736983121197045828L;
-
-    public GreaterThan(Comparable<T> value) {
-        super(value);
-    }
-
-    @Override
-    protected String getName() {
-        return "gt";
-    }
-
-    @Override
-    protected boolean matchResult(int result) {
-        return result > 0;
-    }    
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public class GreaterThan<T extends Comparable<T>> extends CompareTo<T> {
+
+    private static final long serialVersionUID = 2736983121197045828L;
+
+    public GreaterThan(final Comparable<T> value) {
+        super(value);
+    }
+
+    @Override
+    protected String getName() {
+        return "gt";
+    }
+
+    @Override
+    protected boolean matchResult(final int result) {
+        return result > 0;
+    }
+}
diff --git a/src/org/easymock/internal/matchers/InstanceOf.java b/src/org/easymock/internal/matchers/InstanceOf.java
index ca81cee..088befe 100644
--- a/src/org/easymock/internal/matchers/InstanceOf.java
+++ b/src/org/easymock/internal/matchers/InstanceOf.java
@@ -1,28 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class InstanceOf implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -551735356674347591L;
-
-    private final Class<?> clazz;
-
-    public InstanceOf(Class<?> clazz) {
-        this.clazz = clazz;
-    }
-
-    public boolean matches(Object actual) {
-        return (actual != null) && clazz.isAssignableFrom(actual.getClass());
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("isA(" + clazz.getName() + ")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class InstanceOf implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -551735356674347591L;
+
+    private final Class<?> clazz;
+
+    public InstanceOf(final Class<?> clazz) {
+        this.clazz = clazz;
+    }
+
+    public boolean matches(final Object actual) {
+        return (actual != null) && clazz.isAssignableFrom(actual.getClass());
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("isA(" + clazz.getName() + ")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/LessOrEqual.java b/src/org/easymock/internal/matchers/LessOrEqual.java
index cbb92f2..70efe26 100644
--- a/src/org/easymock/internal/matchers/LessOrEqual.java
+++ b/src/org/easymock/internal/matchers/LessOrEqual.java
@@ -1,24 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-public class LessOrEqual<T extends Comparable<T>> extends CompareTo<T> {
-
-    private static final long serialVersionUID = -2485406702001842607L;
-
-    public LessOrEqual(Comparable<T> value) {
-        super(value);
-    }
-
-    @Override
-    protected String getName() {
-        return "leq";
-    }
-
-    @Override
-    protected boolean matchResult(int result) {
-        return result <= 0;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public class LessOrEqual<T extends Comparable<T>> extends CompareTo<T> {
+
+    private static final long serialVersionUID = -2485406702001842607L;
+
+    public LessOrEqual(final Comparable<T> value) {
+        super(value);
+    }
+
+    @Override
+    protected String getName() {
+        return "leq";
+    }
+
+    @Override
+    protected boolean matchResult(final int result) {
+        return result <= 0;
+    }
+}
diff --git a/src/org/easymock/internal/matchers/LessThan.java b/src/org/easymock/internal/matchers/LessThan.java
index 2626814..5fc217a 100644
--- a/src/org/easymock/internal/matchers/LessThan.java
+++ b/src/org/easymock/internal/matchers/LessThan.java
@@ -1,24 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-public class LessThan<T extends Comparable<T>> extends CompareTo<T> {
-
-    private static final long serialVersionUID = 6004888476822043880L;
-
-    public LessThan(Comparable<T> value) {
-        super(value);
-    }
-
-    @Override
-    protected String getName() {
-        return "lt";
-    }
-
-    @Override
-    protected boolean matchResult(int result) {
-        return result < 0;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+/**
+ * @param <T>
+ *            Type of the values compared
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public class LessThan<T extends Comparable<T>> extends CompareTo<T> {
+
+    private static final long serialVersionUID = 6004888476822043880L;
+
+    public LessThan(final Comparable<T> value) {
+        super(value);
+    }
+
+    @Override
+    protected String getName() {
+        return "lt";
+    }
+
+    @Override
+    protected boolean matchResult(final int result) {
+        return result < 0;
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Matches.java b/src/org/easymock/internal/matchers/Matches.java
index 6c7b8b4..d33d05e 100644
--- a/src/org/easymock/internal/matchers/Matches.java
+++ b/src/org/easymock/internal/matchers/Matches.java
@@ -1,29 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Matches implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -6657694947057597484L;
-
-    private final String regex;
-
-    public Matches(String regex) {
-        this.regex = regex;
-    }
-
-    public boolean matches(Object actual) {
-        return (actual instanceof String) && ((String) actual).matches(regex);
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("matches(\"" + regex.replaceAll("\\\\", "\\\\\\\\")
-                + "\")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Matches implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -6657694947057597484L;
+
+    private final String regex;
+
+    public Matches(final String regex) {
+        this.regex = regex;
+    }
+
+    public boolean matches(final Object actual) {
+        return (actual instanceof String) && ((String) actual).matches(regex);
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("matches(\"" + regex.replaceAll("\\\\", "\\\\\\\\") + "\")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Not.java b/src/org/easymock/internal/matchers/Not.java
index 4d8a2c7..efb46ec 100644
--- a/src/org/easymock/internal/matchers/Not.java
+++ b/src/org/easymock/internal/matchers/Not.java
@@ -1,30 +1,44 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Not implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -5160559075998939348L;
-
-    private final IArgumentMatcher first;
-
-    public Not(IArgumentMatcher first) {
-        this.first = first;
-    }
-
-    public boolean matches(Object actual) {
-        return !first.matches(actual);
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("not(");
-        first.appendTo(buffer);
-        buffer.append(")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Not implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -5160559075998939348L;
+
+    private final IArgumentMatcher first;
+
+    public Not(final IArgumentMatcher first) {
+        this.first = first;
+    }
+
+    public boolean matches(final Object actual) {
+        return !first.matches(actual);
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("not(");
+        first.appendTo(buffer);
+        buffer.append(")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/NotNull.java b/src/org/easymock/internal/matchers/NotNull.java
index 0a0edb2..dae6992 100644
--- a/src/org/easymock/internal/matchers/NotNull.java
+++ b/src/org/easymock/internal/matchers/NotNull.java
@@ -1,28 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class NotNull implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -2689588759855326190L;
-
-    public static final NotNull NOT_NULL = new NotNull();
-    
-    private NotNull() {
-        
-    }
-    
-    public boolean matches(Object actual) {
-        return actual != null;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("notNull()");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public final class NotNull implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -2689588759855326190L;
+
+    public static final NotNull NOT_NULL = new NotNull();
+
+    private NotNull() {
+
+    }
+
+    public boolean matches(final Object actual) {
+        return actual != null;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("notNull()");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Null.java b/src/org/easymock/internal/matchers/Null.java
index c94cf5e..ed1a430 100644
--- a/src/org/easymock/internal/matchers/Null.java
+++ b/src/org/easymock/internal/matchers/Null.java
@@ -1,27 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Null implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = 6077244839421122011L;
-
-    public static final Null NULL = new Null();
-
-    private Null() {
-    }
-
-    public boolean matches(Object actual) {
-        return actual == null;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("isNull()");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Null implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = 6077244839421122011L;
+
+    public static final Null NULL = new Null();
+
+    private Null() {
+    }
+
+    public boolean matches(final Object actual) {
+        return actual == null;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("isNull()");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Or.java b/src/org/easymock/internal/matchers/Or.java
index b71c0da..ea2f839 100644
--- a/src/org/easymock/internal/matchers/Or.java
+++ b/src/org/easymock/internal/matchers/Or.java
@@ -1,42 +1,56 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-
-import org.easymock.IArgumentMatcher;
-
-public class Or implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -5701204283180444317L;
-
-    private final List<IArgumentMatcher> matchers;
-
-    public Or(List<IArgumentMatcher> matchers) {
-        this.matchers = matchers;
-    }
-
-    public boolean matches(Object actual) {
-        for (IArgumentMatcher matcher : matchers) {
-            if (matcher.matches(actual)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("or(");
-        for (Iterator<IArgumentMatcher> it = matchers.iterator(); it.hasNext();) {
-            it.next().appendTo(buffer);
-            if (it.hasNext()) {
-                buffer.append(", ");
-            }
-        }
-        buffer.append(")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Or implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -5701204283180444317L;
+
+    private final List<IArgumentMatcher> matchers;
+
+    public Or(final List<IArgumentMatcher> matchers) {
+        this.matchers = matchers;
+    }
+
+    public boolean matches(final Object actual) {
+        for (final IArgumentMatcher matcher : matchers) {
+            if (matcher.matches(actual)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("or(");
+        for (final Iterator<IArgumentMatcher> it = matchers.iterator(); it.hasNext();) {
+            it.next().appendTo(buffer);
+            if (it.hasNext()) {
+                buffer.append(", ");
+            }
+        }
+        buffer.append(")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/Same.java b/src/org/easymock/internal/matchers/Same.java
index 8ac6ecf..4335573 100644
--- a/src/org/easymock/internal/matchers/Same.java
+++ b/src/org/easymock/internal/matchers/Same.java
@@ -1,40 +1,45 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class Same implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = 1094930851962278376L;
-    
-    private final Object expected;
-
-    public Same(Object expected) {
-        this.expected = expected;
-    }
-
-    public boolean matches(Object actual) {
-        return expected == actual;
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("same(");
-        appendQuoting(buffer);
-        buffer.append(expected);
-        appendQuoting(buffer);
-        buffer.append(")");
-    }
-
-    private void appendQuoting(StringBuffer buffer) {
-        if (expected instanceof String) {
-            buffer.append("\"");
-        } else if (expected instanceof Character) {
-            buffer.append("'");
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+import org.easymock.internal.ArgumentToString;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class Same implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = 1094930851962278376L;
+
+    private final Object expected;
+
+    public Same(final Object expected) {
+        this.expected = expected;
+    }
+
+    public boolean matches(final Object actual) {
+        return expected == actual;
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("same(");
+        ArgumentToString.appendArgument(expected, buffer);
+        buffer.append(")");
+    }
+}
diff --git a/src/org/easymock/internal/matchers/StartsWith.java b/src/org/easymock/internal/matchers/StartsWith.java
index 782bc3d..84cf1f8 100644
--- a/src/org/easymock/internal/matchers/StartsWith.java
+++ b/src/org/easymock/internal/matchers/StartsWith.java
@@ -1,29 +1,42 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.internal.matchers;
-
-import java.io.Serializable;
-
-import org.easymock.IArgumentMatcher;
-
-public class StartsWith implements IArgumentMatcher, Serializable {
-
-    private static final long serialVersionUID = -658998692584342514L;
-    
-    private final String prefix;
-
-    public StartsWith(String prefix) {
-        this.prefix = prefix;
-    }
-
-    public boolean matches(Object actual) {
-        return (actual instanceof String)
-                && ((String) actual).startsWith(prefix);
-    }
-
-    public void appendTo(StringBuffer buffer) {
-        buffer.append("startsWith(\"" + prefix + "\")");
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.internal.matchers;
+
+import java.io.Serializable;
+
+import org.easymock.IArgumentMatcher;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class StartsWith implements IArgumentMatcher, Serializable {
+
+    private static final long serialVersionUID = -658998692584342514L;
+
+    private final String prefix;
+
+    public StartsWith(final String prefix) {
+        this.prefix = prefix;
+    }
+
+    public boolean matches(final Object actual) {
+        return (actual instanceof String) && ((String) actual).startsWith(prefix);
+    }
+
+    public void appendTo(final StringBuffer buffer) {
+        buffer.append("startsWith(\"" + prefix + "\")");
+    }
+}
diff --git a/tests/org/easymock/tests/ArgumentToStringTest.java b/tests/org/easymock/tests/ArgumentToStringTest.java
new file mode 100644
index 0000000..bdd9719
--- /dev/null
+++ b/tests/org/easymock/tests/ArgumentToStringTest.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import org.easymock.internal.ArgumentToString;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ArgumentToStringTest {
+
+    private StringBuffer buffer;
+
+    @Before
+    public void setUp() {
+        buffer = new StringBuffer();
+    }
+
+    @Test
+    public void testAppendArgument_null() {
+        assertString("null", null);
+    }
+
+    @Test
+    public void testAppendArgument_String() {
+        assertString("\"hello\"", "hello");
+    }
+
+    @Test
+    public void testAppendArgument_Character() {
+        assertString("'c'", Character.valueOf('c'));
+    }
+
+    @Test
+    public void testAppendArgument_Array() {
+        assertString("[\"a\", \"b\"]", new String[] { "a", "b" });
+    }
+
+    @Test
+    public void testAppendArgument_Full() {
+        assertString("[3, 4, [\"a\", \"b\"], null]", new Object[] { 3, 4, new String[] { "a", "b" }, null });
+    }
+
+    private void assertString(final String expected, final Object actual) {
+        ArgumentToString.appendArgument(actual, buffer);
+        assertEquals(expected, buffer.toString());
+    }
+
+    @Test
+    public void testArgumentToString() {
+        final String actual = ArgumentToString.argumentToString(Boolean.TRUE);
+        assertEquals(Boolean.TRUE.toString(), actual);
+    }
+
+    @Test
+    public void testArgumentsToString() {
+        final String actual = ArgumentToString.argumentsToString(Boolean.TRUE, Boolean.FALSE);
+        assertEquals("true, false", actual);
+    }
+
+    @Test
+    public void testArgumentsToString_null() {
+        final String actual = ArgumentToString.argumentsToString((Object[]) null);
+        assertEquals("", actual);
+    }
+}
diff --git a/tests/org/easymock/tests/ArgumentsMatcherTest.java b/tests/org/easymock/tests/ArgumentsMatcherTest.java
deleted file mode 100644
index 13df807..0000000
--- a/tests/org/easymock/tests/ArgumentsMatcherTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.AbstractMatcher;
-import org.easymock.ArgumentsMatcher;
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class ArgumentsMatcherTest {
-
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setUp() {
-        control = MockControl.createStrictControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void expectedArgumentsDelegatedToMatcher() {
-        mock.twoArgumentMethod(0, 5);
-        control.setMatcher(new AbstractMatcher() {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public boolean matches(Object[] expected, Object[] actual) {
-                assertEquals(0, ((Integer) expected[0]).intValue());
-                assertEquals(5, ((Integer) expected[1]).intValue());
-                assertEquals(1, ((Integer) actual[0]).intValue());
-                assertEquals(6, ((Integer) actual[1]).intValue());
-                return true;
-            }
-        });
-        mock.simpleMethod();
-        control.replay();
-        mock.twoArgumentMethod(1, 6);
-        mock.simpleMethod();
-        control.verify();
-    }
-
-    @Test
-    public void expectedArgumentsDelegatedToMatcher2() {
-        mock.threeArgumentMethod(7, "", "A test");
-        control.setMatcher(new AbstractMatcher() {
-            
-            private static final long serialVersionUID = 1L;
-            
-            @Override
-            public boolean matches(Object[] expected, Object[] actual) {
-                int expectedInt = ((Integer) expected[0]).intValue();
-                int actualInt = ((Integer) actual[0]).intValue();
-                return expectedInt < actualInt;
-            }
-        });
-        control.setReturnValue("1");
-        mock.threeArgumentMethod(6, "", "A test");
-        control.setReturnValue("2");
-        mock.threeArgumentMethod(12, "", "A test");
-        control.setReturnValue("3");
-
-        control.replay();
-        mock.threeArgumentMethod(9, "test", "test");
-        mock.threeArgumentMethod(8, "test", "test");
-        mock.threeArgumentMethod(13, "test", "test");
-        control.verify();
-    }
-
-    @Test
-    public void errorString() {
-        mock.twoArgumentMethod(0, 5);
-        control.setMatcher(new ArgumentsMatcher() {
-            public boolean matches(Object[] expected, Object[] actual) {
-                return false;
-            }
-
-            public String toString(Object[] arguments) {
-                return "<<" + arguments[0] + ">>";
-            }
-        });
-        control.replay();
-        boolean failed = false;
-        try {
-            mock.twoArgumentMethod(1, 5);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals("\n  Unexpected method call twoArgumentMethod(1, 5):"
-                    + "\n    twoArgumentMethod(<<0>>): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("exception expected");
-        }
-    }
-
-    @Test
-    public void settingTheSameMatcherIsOk() {
-        try {
-            mock.twoArgumentMethod(1, 2);
-            control.setMatcher(MockControl.ARRAY_MATCHER);
-            control.setMatcher(MockControl.ARRAY_MATCHER);
-            mock.twoArgumentMethod(1, 2);
-            control.setMatcher(MockControl.ARRAY_MATCHER);
-
-        } catch (IllegalStateException unexpected) {
-            fail("no exception should be thrown if the same matcher is set twice");
-        }
-    }
-
-    @Test
-    public void abstractMatcher() {
-        AbstractMatcher trueMatcher = new AbstractMatcher() {
-            
-            private static final long serialVersionUID = 1L;
-            
-            protected boolean parameterMatches(Object expected, Object actual) {
-                return true;
-            }
-        };
-        Object[] arrayWithNull = new Object[] { null };
-        Object[] arrayWithObject = new Object[] { new Object() };
-        assertFalse(trueMatcher.matches(arrayWithNull, arrayWithObject));
-        assertFalse(trueMatcher.matches(arrayWithObject, arrayWithNull));
-    }
-
-    @Test
-    public void abstractMatcherToStringHandlesNullArray() {
-        AbstractMatcher matcher = new AbstractMatcher() {            
-            private static final long serialVersionUID = 1L;
-        };
-        assertEquals("", matcher.toString(null));
-    }
-
-}
\ No newline at end of file
diff --git a/tests/org/easymock/tests/ArrayMatcherTest.java b/tests/org/easymock/tests/ArrayMatcherTest.java
deleted file mode 100644
index 62b0084..0000000
--- a/tests/org/easymock/tests/ArrayMatcherTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.ArgumentsMatcher;
-import org.easymock.MockControl;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class ArrayMatcherTest {
-
-    private static ArgumentsMatcher MATCHER = MockControl.ARRAY_MATCHER;
-
-    @Test
-    public void booleanArray() {
-        assertTrue(equals(new boolean[] { true }, new boolean[] { true }));
-        assertFalse(equals(new boolean[] { true }, new boolean[] { false }));
-    }
-
-    @Test
-    public void byteArray() {
-        assertTrue(equals(new byte[] { 6 }, new byte[] { 6 }));
-        assertFalse(equals(new byte[] { 6 }, new byte[] { 7 }));
-    }
-
-    @Test
-    public void charArray() {
-        assertTrue(equals(new char[] { 'x' }, new char[] { 'x' }));
-        assertFalse(equals(new char[] { 'x' }, new char[] { 'y' }));
-    }
-
-    @Test
-    public void doubleArray() {
-        assertTrue(equals(new double[] { 6.0 }, new double[] { 6.0 }));
-        assertFalse(equals(new double[] { 6.0 }, new double[] { 7.0 }));
-    }
-
-    @Test
-    public void floatArray() {
-        assertTrue(equals(new float[] { 6.0F }, new float[] { 6.0F }));
-        assertFalse(equals(new float[] { 6.0F }, new float[] { 7.0F }));
-    }
-
-    @Test
-    public void intArray() {
-        assertTrue(equals(new int[] { 6 }, new int[] { 6 }));
-        assertFalse(equals(new int[] { 6 }, new int[] { 7 }));
-    }
-
-    @Test
-    public void longArray() {
-        assertTrue(equals(new long[] { 6 }, new long[] { 6 }));
-        assertFalse(equals(new long[] { 6 }, new long[] { 7 }));
-    }
-
-    @Test
-    public void shortArray() {
-        assertTrue(equals(new short[] { 6 }, new short[] { 6 }));
-        assertFalse(equals(new short[] { 6 }, new short[] { 7 }));
-    }
-
-    @Test
-    public void objectArray() {
-        assertTrue(equals(new String[] { "1", "2" }, new String[] { "1", "2" }));
-        assertFalse(equals(new String[] { "1", "2" }, new String[] { "2", "2" }));
-    }
-
-    @Test
-    public void nonArray() {
-        assertTrue(equals("1", "1"));
-        assertFalse(equals("1", "2"));
-    }
-
-    @Test
-    public void testToString() {
-        assertEquals("[true, false]", stringFor(new boolean[] { true, false }));
-        assertEquals("[6, 7]", stringFor(new byte[] { 6, 7 }));
-        assertEquals("['x', 'y']", stringFor(new char[] { 'x', 'y' }));
-        assertEquals("[6.0, 7.0]", stringFor(new double[] { 6, 7 }));
-        assertEquals("[6.0, 7.0]", stringFor(new float[] { 6, 7 }));
-        assertEquals("[6, 7]", stringFor(new int[] { 6, 7 }));
-        assertEquals("[6, 7]", stringFor(new long[] { 6, 7 }));
-        assertEquals("[6, 7]", stringFor(new short[] { 6, 7 }));
-        assertEquals("[\"1\", \"2\"]", stringFor(new String[] { "1", "2" }));
-        assertEquals("[\"1\", \"2\"]", stringFor(new Object[] { "1", "2" }));
-    }
-
-    @Test
-    public void toStringMixed() {
-        assertEquals("3, [\"1\", 2.0], \"Test\"", MATCHER
-                .toString(new Object[] { new Integer(3),
-                        new Object[] { "1", new Float(2.0) }, "Test" }));
-    }
-
-    private String stringFor(Object argument) {
-        return MATCHER.toString(new Object[] { argument });
-    }
-
-    private boolean equals(Object o1, Object o2) {
-        Object[] expected = new Object[] { o1 };
-        Object[] actual = new Object[] { o2 };
-        return MATCHER.matches(expected, actual);
-    }
-}
diff --git a/tests/org/easymock/tests/BaseEasyMockRunnerTest.java b/tests/org/easymock/tests/BaseEasyMockRunnerTest.java
new file mode 100644
index 0000000..2370276
--- /dev/null
+++ b/tests/org/easymock/tests/BaseEasyMockRunnerTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import org.easymock.EasyMockSupport;
+
+/**
+ * @author Henri Tremblay
+ */
+public abstract class BaseEasyMockRunnerTest  extends EasyMockSupport{
+
+    protected IMethods superMock;
+}
diff --git a/tests/org/easymock/tests/CapturesMatcherTest.java b/tests/org/easymock/tests/CapturesMatcherTest.java
index f5e8bf7..0837da7 100644
--- a/tests/org/easymock/tests/CapturesMatcherTest.java
+++ b/tests/org/easymock/tests/CapturesMatcherTest.java
@@ -1,37 +1,77 @@
-/*
- * Copyright (c) 2003-2008 OFFIS, Henri Tremblay. 
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.Capture;
-import org.easymock.internal.matchers.Captures;
-import org.junit.Test;
-
-
-public class CapturesMatcherTest {
-
-    private Capture<String> capture = new Capture<String>();
-    private Captures<String> matcher = new Captures<String>(capture);
-    
-    @Test
-    public void test() {
-        StringBuffer buffer = new StringBuffer();
-        matcher.appendTo(buffer);
-        assertEquals("capture(Nothing captured yet)", buffer.toString());
-        
-        assertTrue(matcher.matches(null));
-        
-        buffer.delete(0, buffer.length());        
-        matcher.appendTo(buffer);
-        assertEquals("capture(null)", buffer.toString());
-        
-        assertTrue(matcher.matches("s"));
-        
-        buffer.delete(0, buffer.length());        
-        matcher.appendTo(buffer);
-        assertEquals("capture(s)", buffer.toString());
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.easymock.internal.Invocation;
+import org.easymock.internal.LastControl;
+import org.easymock.internal.matchers.Captures;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class CapturesMatcherTest {
+
+    private final Capture<String> capture = new Capture<String>(CaptureType.ALL);
+
+    private final Captures<String> matcher = new Captures<String>(capture);
+
+    private StringBuffer buffer;
+
+    @Before
+    public void setUp() throws Exception {
+        LastControl.pushCurrentInvocation(new Invocation(this, getClass().getMethod("test"), new Object[0]));
+        buffer = new StringBuffer();
+    }
+
+    @After
+    public void tearDown() {
+        LastControl.popCurrentInvocation();
+    }
+
+    @Test
+    public void test() throws Exception {
+
+        matcher.appendTo(buffer);
+        assertEquals("capture(Nothing captured yet)", buffer.toString());
+
+        assertTrue(matcher.matches(null));
+
+        matcher.validateCapture();
+
+        clearBuffer();
+        matcher.appendTo(buffer);
+        assertEquals("capture(null)", buffer.toString());
+
+        assertTrue(matcher.matches("s"));
+
+        matcher.validateCapture();
+
+        clearBuffer();
+        matcher.appendTo(buffer);
+        assertEquals("capture([null, s])", buffer.toString());
+    }
+
+    private void clearBuffer() {
+        buffer.delete(0, buffer.length());
+    }
+}
diff --git a/tests/org/easymock/tests/CglibTest.java b/tests/org/easymock/tests/CglibTest.java
new file mode 100644
index 0000000..09a5424
--- /dev/null
+++ b/tests/org/easymock/tests/CglibTest.java
@@ -0,0 +1,70 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+import net.sf.cglib.proxy.*;
+
+import org.easymock.internal.ClassInstantiatorFactory;
+import org.junit.Test;
+
+/**
+ * This test case is used to make sure that the way cglib is used is providing
+ * the expected behavior
+ * 
+ * @author Henri Tremblay
+ */
+public class CglibTest {
+
+    /**
+     * Check that an interceptor is used by only one instance of a class
+     * 
+     * @throws Exception
+     */
+    @Test
+    public void test() throws Exception {
+
+//        final Factory f1 = createMock();
+//        final Factory f2 = createMock();
+//
+//        assertNotSame(f1.getCallback(0), f2.getCallback(0));
+    }
+
+    private Factory createMock() throws Exception {
+        final MethodInterceptor interceptor = new MethodInterceptor() {
+            public Object intercept(final Object obj, final Method method, final Object[] args,
+                    final MethodProxy proxy) throws Throwable {
+                return proxy.invokeSuper(obj, args);
+            }
+        };
+
+        final Enhancer enhancer = new Enhancer();
+        enhancer.setSuperclass(ArrayList.class);
+        enhancer.setCallbackType(MethodInterceptor.class);
+
+        final Class<?> mockClass = enhancer.createClass();
+
+        Enhancer.registerCallbacks(mockClass, new Callback[] { interceptor });
+
+        final Factory f = (Factory) ClassInstantiatorFactory.getInstantiator().newInstance(mockClass);
+
+        f.getCallback(0);
+
+        return f;
+    }
+}
diff --git a/tests/org/easymock/tests/ClassInstantiatorFactoryTest.java b/tests/org/easymock/tests/ClassInstantiatorFactoryTest.java
new file mode 100644
index 0000000..dbf3b17
--- /dev/null
+++ b/tests/org/easymock/tests/ClassInstantiatorFactoryTest.java
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import org.easymock.internal.ClassInstantiatorFactory;
+import org.easymock.internal.DefaultClassInstantiator;
+import org.easymock.internal.IClassInstantiator;
+import org.easymock.internal.ObjenesisClassInstantiator;
+import org.junit.After;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ClassInstantiatorFactoryTest {
+
+    @After
+    public void tearDown() throws Exception {
+        // put back the default to prevent side effects on other tests
+        ClassInstantiatorFactory.setDefaultInstantiator();
+    }
+
+    @Test
+    public void getInstantiator_Default() {
+        final IClassInstantiator instantiator = ClassInstantiatorFactory.getInstantiator();
+        assertTrue(instantiator instanceof ObjenesisClassInstantiator);
+    }
+
+    @Test
+    public void getInstantiator_Overriden() {
+        ClassInstantiatorFactory.setInstantiator(new DefaultClassInstantiator());
+        final IClassInstantiator instantiator = ClassInstantiatorFactory.getInstantiator();
+        assertTrue(instantiator instanceof DefaultClassInstantiator);
+    }
+
+    @Test
+    public void getInstantiator_BackToDefault() {
+        ClassInstantiatorFactory.setInstantiator(new DefaultClassInstantiator());
+        ClassInstantiatorFactory.setDefaultInstantiator();
+        final IClassInstantiator instantiator = ClassInstantiatorFactory.getInstantiator();
+        assertTrue(instantiator instanceof ObjenesisClassInstantiator);
+    }
+
+    @Test
+    public void getJVM() {
+        assertEquals(System.getProperty("java.vm.vendor"), ClassInstantiatorFactory.getJVM());
+    }
+}
diff --git a/tests/org/easymock/tests/ConstructorTest.java b/tests/org/easymock/tests/ConstructorTest.java
new file mode 100644
index 0000000..eca1921
--- /dev/null
+++ b/tests/org/easymock/tests/ConstructorTest.java
@@ -0,0 +1,72 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ConstructorTest {
+
+    public static class FooClass {
+        public void foo() {
+            // Since it's always mocked, it should never be called
+            fail();
+        }
+    }
+
+    public static class EmptyConstructorClass extends FooClass {
+    }
+
+    public static class ConstructorCallingPublicMethodClass extends FooClass {
+
+        public ConstructorCallingPublicMethodClass() {
+            foo();
+        }
+    }
+
+    private void testConstructor(final Class<? extends FooClass> mockedClass) {
+        final FooClass mock = createMock(mockedClass);
+        assertTrue(mockedClass.isAssignableFrom(mock.getClass()));
+        mock.foo();
+        expectLastCall();
+        replay(mock);
+        mock.foo();
+        verify(mock);
+    }
+
+    /**
+     * Test if a class with an empty constructor is mocked correctly.
+     */
+//    @Test
+    public void emptyConstructor() {
+        testConstructor(EmptyConstructorClass.class);
+    }
+
+    /**
+     * Test that a constructor calling a mocked method (in this case a public
+     * one) is mocked correctly. The expected behavior is that the mocked method
+     * won't be called and just be ignored
+     */
+    @Test
+    public void constructorCallingPublicMethod() {
+        testConstructor(ConstructorCallingPublicMethodClass.class);
+    }
+}
diff --git a/tests/org/easymock/tests/DefaultClassInstantiatorTest.java b/tests/org/easymock/tests/DefaultClassInstantiatorTest.java
new file mode 100644
index 0000000..7945f78
--- /dev/null
+++ b/tests/org/easymock/tests/DefaultClassInstantiatorTest.java
@@ -0,0 +1,217 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import java.io.Serializable;
+
+import org.easymock.internal.ClassInstantiatorFactory;
+import org.easymock.internal.DefaultClassInstantiator;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * Class testing the default instantiator. I'm cheating a little bit here since
+ * I'm not unit testing directly the class. The reason I'm doing this is that I
+ * want to make sure it works well with the cglib class and not the actual
+ * mocked class.
+ * 
+ * @author Henri Tremblay
+ */
+public class DefaultClassInstantiatorTest {
+
+    public static class PrimitiveParamClass {
+        public PrimitiveParamClass(final int i) {
+        }
+    }
+
+    public static class FinalParamClass {
+        public FinalParamClass(final String i) {
+        }
+    }
+
+    public static class ProtectedConstructorClass {
+        protected ProtectedConstructorClass() {
+        }
+    }
+
+    public static class ProtectedWithPrimitiveConstructorClass {
+        protected ProtectedWithPrimitiveConstructorClass(final int i) {
+        }
+    }
+
+    public static class ParamClass {
+        public ParamClass(final FinalParamClass f) {
+        }
+    }
+
+    public static class ObjectClass {
+        public ObjectClass(final Object c) {
+        }
+    }
+
+    public static class ObjectParamClass {
+        public ObjectParamClass(final ParamClass c) {
+        }
+    }
+
+    public static class PrivateConstructorClass {
+        private PrivateConstructorClass() {
+        }
+    }
+
+    public static class ConstructorWithCodeClass {
+        public ConstructorWithCodeClass() {
+            throw new RuntimeException();
+        }
+    }
+
+    @SuppressWarnings("serial")
+    public static class SerializableClass implements Serializable {
+        public SerializableClass() {
+            throw new RuntimeException();
+        }
+    }
+
+    public static class SerializableWithUIDClass implements Serializable {
+
+        private static final long serialVersionUID = -1;
+
+        public SerializableWithUIDClass() {
+            throw new RuntimeException();
+        }
+    }
+
+    @SuppressWarnings("serial")
+    public static class BadlyDoneSerializableClass implements Serializable {
+
+        private final long serialVersionUID = 2; // not static
+
+        public BadlyDoneSerializableClass() {
+            throw new RuntimeException();
+        }
+    }
+
+    private final String vendor = null;
+
+    @BeforeClass
+    public static void setUp() {
+        // Set the default instantiator
+        ClassInstantiatorFactory.setInstantiator(new DefaultClassInstantiator());
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        // Set the value back to be clean
+        ClassInstantiatorFactory.setDefaultInstantiator();
+    }
+
+    @Test
+    public void emptyConstructor() {
+        checkInstantiation(DefaultClassInstantiator.class);
+    }
+
+    @Test
+    public void primitiveType() {
+        checkInstantiation(PrimitiveParamClass.class);
+    }
+
+    @Test
+    @Ignore // Fails on Java 7 for a currently unknown reason
+    public void finalType() {
+        checkInstantiation(FinalParamClass.class);
+    }
+
+    @Test
+    public void protectedConstructor() {
+        checkInstantiation(ProtectedConstructorClass.class);
+    }
+
+    @Test
+    public void protectedWithPrimitiveConstructor() {
+        checkInstantiation(ProtectedWithPrimitiveConstructorClass.class);
+    }
+
+    @Test
+    public void object() {
+        checkInstantiation(ObjectClass.class);
+    }
+
+    @Test
+    @Ignore // Fails on Java 7 for a currently unknown reason
+    public void objectParamRecursion() {
+        checkInstantiation(ObjectParamClass.class);
+    }
+
+    @Test
+    public void constructorWithCodeLimitation() {
+        try {
+            createMock(ConstructorWithCodeClass.class);
+            fail("Shouldn't be possible to mock, code in constructor should crash");
+        } catch (final Exception e) {
+        }
+    }
+
+    @Test
+    public void privateConstructorLimitation() {
+        try {
+            createMock(PrivateConstructorClass.class);
+            fail("Shouldn't be able to mock a class with a private constructor using DefaultInstantiator");
+        } catch (final Exception e) {
+        }
+    }
+
+    @Test
+    public void privateConstructor() {
+        final DefaultClassInstantiator instantiator = new DefaultClassInstantiator();
+        try {
+            instantiator.newInstance(PrivateConstructorClass.class);
+            fail("Shouldn't be able to mock a class with a private constructor using DefaultInstantiator");
+        } catch (final Exception e) {
+        }
+    }
+
+    @Test
+    public void newInstance() {
+        checkInstantiation(DefaultClassInstantiator.class);
+    }
+
+    @Test
+    public void serializable() {
+        checkInstantiation(SerializableClass.class);
+    }
+
+    @Test
+    public void badSerializable() throws Exception {
+        final DefaultClassInstantiator instantiator = new DefaultClassInstantiator();
+        assertTrue(instantiator.newInstance(BadlyDoneSerializableClass.class) instanceof BadlyDoneSerializableClass);
+    }
+
+    @Test
+    public void serializableWithUID() throws Exception {
+        final DefaultClassInstantiator instantiator = new DefaultClassInstantiator();
+        assertTrue(instantiator.newInstance(SerializableWithUIDClass.class) instanceof SerializableWithUIDClass);
+    }
+
+    private <T> void checkInstantiation(final Class<T> clazz) {
+        final T mock = createMock(clazz);
+        assertTrue(clazz.isAssignableFrom(mock.getClass()));
+    }
+}
diff --git a/tests/org/easymock/tests/DefaultMatcherTest.java b/tests/org/easymock/tests/DefaultMatcherTest.java
deleted file mode 100644
index bdfdf47..0000000
--- a/tests/org/easymock/tests/DefaultMatcherTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class DefaultMatcherTest {
-
-    public static interface ArrayInterface {
-        void methodA(int[] argument);
-
-        void methodB(int[] argument);
-    }
-
-    private MockControl<ArrayInterface> control;
-
-    private ArrayInterface mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(ArrayInterface.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void defaultMatcher() {
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-
-        mock.methodA(new int[] { 1, 1 });
-        mock.methodB(new int[] { 2, 2 });
-
-        control.replay();
-
-        mock.methodA(new int[] { 1, 1 });
-        mock.methodB(new int[] { 2, 2 });
-
-        control.verify();
-    }
-
-    @Test
-    public void failInReplayState() {
-        control.replay();
-        try {
-            control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    @Test
-    public void failIfDefaultMatcherSetTwice() {
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-        try {
-            control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-            fail();
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "default matcher can only be set once directly after creation of the MockControl",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void defaultMatcherSetTooLate() {
-        int[] integers = new int[] { 1, 1 };
-        int[] integers2 = new int[] { 2, 2 };
-        mock.methodA(integers);
-        control.setVoidCallable();
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-        mock.methodA(integers2);
-        control.setVoidCallable();
-        control.replay();
-
-        boolean failed = true;
-        try {
-            mock.methodA(new int[] { 1, 1 });
-            failed = false;
-        } catch (AssertionError expected) {
-        }
-        if (!failed) {
-            fail();
-        }
-        mock.methodA(integers);
-        mock.methodA(new int[] { 2, 2 });
-        control.verify();
-    }
-}
diff --git a/tests/org/easymock/tests/EqualsMatcherTest.java b/tests/org/easymock/tests/EqualsMatcherTest.java
deleted file mode 100644
index 3298a15..0000000
--- a/tests/org/easymock/tests/EqualsMatcherTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.ArgumentsMatcher;
-import org.easymock.MockControl;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class EqualsMatcherTest {
-    final ArgumentsMatcher MATCHER = MockControl.EQUALS_MATCHER;
-
-    @Test
-    public void equalsMatcher() {
-        assertTrue(MATCHER.matches(null, null));
-        assertFalse(MATCHER.matches(null, new Object[0]));
-        assertFalse(MATCHER.matches(new Object[0], null));
-        assertFalse(MATCHER.matches(new Object[] { "" }, new Object[] { null }));
-        assertFalse(MATCHER.matches(new Object[] { null }, new Object[] { "" }));
-        assertTrue(MATCHER
-                .matches(new Object[] { null }, new Object[] { null }));
-        assertTrue(MATCHER.matches(new Object[] { "x" }, new Object[] { "x" }));
-    }
-
-    @Test
-    public void differentNumberOfArguments() {
-        assertFalse(MATCHER.matches(new Object[2], new Object[3]));
-    }
-}
\ No newline at end of file
diff --git a/tests/org/easymock/tests/ErrorMessageTest.java b/tests/org/easymock/tests/ErrorMessageTest.java
new file mode 100644
index 0000000..949d825
--- /dev/null
+++ b/tests/org/easymock/tests/ErrorMessageTest.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import org.easymock.internal.ErrorMessage;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ErrorMessageTest {
+
+    @Test
+    public void testGetters() {
+        final ErrorMessage m = new ErrorMessage(true, "error", 3);
+        assertTrue(m.isMatching());
+        assertEquals("error", m.getMessage());
+        assertEquals(3, m.getActualCount());
+    }
+
+    @Test
+    public void testAppendTo_matchingOne() {
+        final StringBuilder sb = new StringBuilder(20);
+        final ErrorMessage m = new ErrorMessage(true, "error()", 2);
+        m.appendTo(sb, 1);
+        assertEquals("\n    error(), actual: 3", sb.toString());
+    }
+
+    @Test
+    public void testAppendTo_matchingNone() {
+        final StringBuilder sb = new StringBuilder(20);
+        final ErrorMessage m = new ErrorMessage(false, "error()", 2);
+        m.appendTo(sb, 0);
+        assertEquals("\n    error(), actual: 2", sb.toString());
+    }
+
+    @Test
+    public void testAppendTo_matchingMultiple() {
+        final StringBuilder sb = new StringBuilder(20);
+        final ErrorMessage m = new ErrorMessage(true, "error()", 2);
+        m.appendTo(sb, 2);
+        assertEquals("\n    error(), actual: 2 (+1)", sb.toString());
+    }
+}
diff --git a/tests/org/easymock/tests/ExpectedMethodCallTest.java b/tests/org/easymock/tests/ExpectedMethodCallTest.java
index 7a331a1..a27a972 100644
--- a/tests/org/easymock/tests/ExpectedMethodCallTest.java
+++ b/tests/org/easymock/tests/ExpectedMethodCallTest.java
@@ -1,37 +1,50 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.Method;
-
-import org.easymock.internal.ExpectedInvocation;
-import org.easymock.internal.Invocation;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ExpectedMethodCallTest {
-
-    private ExpectedInvocation call;
-
-    @Before
-    public void setup() throws SecurityException, NoSuchMethodException {
-        Object[] arguments1 = new Object[] { "" };
-        Method m = Object.class.getMethod("equals",
-                new Class[] { Object.class });
-        call = new ExpectedInvocation(new Invocation(null, m, arguments1), null);
-    }
-
-    @Test
-    public void testHashCode() {
-        try {
-            call.hashCode();
-            fail();
-        } catch (UnsupportedOperationException expected) {
-            assertEquals("hashCode() is not implemented", expected.getMessage());
-        }
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+
+import org.easymock.internal.ExpectedInvocation;
+import org.easymock.internal.Invocation;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ExpectedMethodCallTest {
+
+    private ExpectedInvocation call;
+
+    @Before
+    public void setup() throws SecurityException, NoSuchMethodException {
+        final Object[] arguments1 = new Object[] { "" };
+        final Method m = Object.class.getMethod("equals", new Class[] { Object.class });
+        call = new ExpectedInvocation(new Invocation(null, m, arguments1), null);
+    }
+
+    @Test
+    public void testHashCode() {
+        try {
+            call.hashCode();
+            fail();
+        } catch (final UnsupportedOperationException expected) {
+            assertEquals("hashCode() is not implemented", expected.getMessage());
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/GenericTest.java b/tests/org/easymock/tests/GenericTest.java
new file mode 100644
index 0000000..e8ed17c
--- /dev/null
+++ b/tests/org/easymock/tests/GenericTest.java
@@ -0,0 +1,123 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import org.easymock.tests2.ChildEquals;
+import org.junit.Test;
+
+import java.util.Collection;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * Bridges are generated methods used for generics. They shouldn't be mocked to
+ * keep delegating correctly to the real implementation.
+ * 
+ * @author Henri Tremblay
+ */
+public class GenericTest {
+
+    public interface C<U> {
+        public void doCMethod(U u);
+    }
+
+    public class B implements C<Integer> {
+        public void doCMethod(final Integer u) {
+            fail("Should be mocked");
+        }
+    }
+
+    @Test
+    public void testTheBridgeMethodIsRecordedNotTheBridge() {
+        final B b = createMock(B.class);
+        b.doCMethod(Integer.valueOf(6));
+        replay(b);
+        ((C<Integer>) b).doCMethod(Integer.valueOf(6));
+        verify(b);
+    }
+
+    /**
+     * Test cglib bug. See ClassProxyFactory.intercept for details
+     */
+    @Test
+    public void testPartialMockingSeesBridgeHasUnmocked() {
+        final ConcreteFoo b = createMockBuilder(ConcreteFoo.class).addMockedMethod("getSomeStrings")
+                .createMock();
+        final AbstractFoo c = b;
+        expect(c.getSomeStrings()).andReturn(null);
+    }
+
+    static abstract class AbstractFoo {
+        public Collection<String> getSomeStrings() {
+            fail("Should be mocked");
+            return null;
+        }
+    }
+
+    public static class ConcreteFoo extends AbstractFoo {
+    }
+
+    /**
+     * The JDK (and not Eclipse) creates a bridge in a concrete class extending
+     * a package scope one. In this case, the bridge contains a call to the
+     * super method. So we want to make sure the mocking is forwarding
+     * correctly.
+     */
+    @Test
+    public void testPackageScope() {
+        final ConcreteFoo b = createMock(ConcreteFoo.class);
+        expect(b.getSomeStrings()).andReturn(null);
+        replay(b);
+        ((AbstractFoo) b).getSomeStrings();
+        verify(b);
+    }
+
+    static abstract class GenericHolder<T> {
+        abstract void set(T value);
+
+        void go(final T value) {
+            set(value);
+        }
+    }
+
+    public static class StringHolder extends GenericHolder<String> {
+        private String value;
+
+        @Override
+        void set(final String value) {
+            this.value = value;
+        }
+    }
+
+    /**
+     * This test makes sure that a bridge method won't be considered mocked.
+     * Bridge are never mocked. Only the underlying method should be.
+     */
+    @Test
+    public void testPartialMockBridgeMethodAreUnmocked() {
+        final StringHolder holder = createMockBuilder(StringHolder.class).createMock();
+        holder.go("hello");
+        assertEquals("hello", holder.value);
+    }
+
+    @Test
+    public void testBridgedEquals() {
+        ChildEquals c = createMock(ChildEquals.class);
+        assertTrue(c.equals(c));
+
+    }
+}
diff --git a/tests/org/easymock/tests/IMethods.java b/tests/org/easymock/tests/IMethods.java
index fbade56..f273f2a 100644
--- a/tests/org/easymock/tests/IMethods.java
+++ b/tests/org/easymock/tests/IMethods.java
@@ -1,88 +1,102 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import java.io.IOException;
-
-public interface IMethods {
-
-    boolean booleanReturningMethod(int index);
-
-    byte byteReturningMethod(int index);
-
-    short shortReturningMethod(int index);
-
-    char charReturningMethod(int index);
-
-    int intReturningMethod(int index);
-
-    long longReturningMethod(int index);
-
-    float floatReturningMethod(int index);
-
-    double doubleReturningMethod(int index);
-
-    Object objectReturningMethod(int index);
-
-    String oneArg(boolean value);
-
-    String oneArg(byte value);
-
-    String oneArg(short value);
-
-    String oneArg(char value);
-
-    String oneArg(int value);
-
-    String oneArg(long value);
-
-    String oneArg(float value);
-
-    String oneArg(double value);
-
-    String oneArg(Object value);
-
-    String oneArg(String value);
-
-    public String throwsNothing(boolean value);
-
-    public String throwsIOException(int count) throws IOException;
-
-    public String throwsError(int count) throws Error;
-
-    void simpleMethod();
-
-    void simpleMethodWithArgument(String argument);
-
-    Object threeArgumentMethod(int valueOne, Object valueTwo, String valueThree);
-
-    void twoArgumentMethod(int one, int two);
-
-    void arrayMethod(String[] strings);
-
-    String oneArray(boolean[] array);
-
-    String oneArray(byte[] array);
-
-    String oneArray(char[] array);
-
-    String oneArray(double[] array);
-
-    String oneArray(float[] array);
-
-    String oneArray(int[] array);
-
-    String oneArray(long[] array);
-
-    String oneArray(short[] array);
-
-    String oneArray(Object[] array);
-
-    String oneArray(String[] array);
-
-    void varargsString(int i, String... string);
-
-    void varargsObject(int i, Object... object);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import java.io.IOException;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public interface IMethods {
+
+    boolean booleanReturningMethod(int index);
+
+    byte byteReturningMethod(int index);
+
+    short shortReturningMethod(int index);
+
+    char charReturningMethod(int index);
+
+    int intReturningMethod(int index);
+
+    long longReturningMethod(int index);
+
+    float floatReturningMethod(int index);
+
+    double doubleReturningMethod(int index);
+
+    Object objectReturningMethod(int index);
+
+    String oneArg(boolean value);
+
+    String oneArg(byte value);
+
+    String oneArg(short value);
+
+    String oneArg(char value);
+
+    String oneArg(int value);
+
+    String oneArg(long value);
+
+    String oneArg(float value);
+
+    String oneArg(double value);
+
+    String oneArg(Object value);
+
+    String oneArg(String value);
+
+    public String throwsNothing(boolean value);
+
+    public String throwsIOException(int count) throws IOException;
+
+    public String throwsError(int count) throws Error;
+
+    void simpleMethod();
+
+    void simpleMethodWithArgument(String argument);
+
+    Object threeArgumentMethod(int valueOne, Object valueTwo, String valueThree);
+
+    void twoArgumentMethod(int one, int two);
+
+    void arrayMethod(String[] strings);
+
+    String oneArray(boolean[] array);
+
+    String oneArray(byte[] array);
+
+    String oneArray(char[] array);
+
+    String oneArray(double[] array);
+
+    String oneArray(float[] array);
+
+    String oneArray(int[] array);
+
+    String oneArray(long[] array);
+
+    String oneArray(short[] array);
+
+    String oneArray(Object[] array);
+
+    String oneArray(String[] array);
+
+    void varargsString(int i, String... string);
+
+    void varargsObject(int i, Object... object);
+}
diff --git a/tests/org/easymock/tests/IVarArgs.java b/tests/org/easymock/tests/IVarArgs.java
index 4f4896e..4f46347 100644
--- a/tests/org/easymock/tests/IVarArgs.java
+++ b/tests/org/easymock/tests/IVarArgs.java
@@ -1,27 +1,41 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-public interface IVarArgs {
-    public void withVarargsString(int value, String... s);
-
-    public void withVarargsObject(int value, Object... o);
-
-    public void withVarargsBoolean(int value, boolean... b);
-
-    public void withVarargsByte(int value, byte... b);
-
-    public void withVarargsChar(int value, char... c);
-
-    public void withVarargsDouble(int value, double... d);
-
-    public void withVarargsFloat(int value, float... f);
-
-    public void withVarargsInt(int value, int... i);
-
-    public void withVarargsLong(int value, long... l);
-
-    public void withVarargsShort(int value, short... s);
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public interface IVarArgs {
+    public void withVarargsString(int value, String... s);
+
+    public void withVarargsObject(int value, Object... o);
+
+    public void withVarargsBoolean(int value, boolean... b);
+
+    public void withVarargsByte(int value, byte... b);
+
+    public void withVarargsChar(int value, char... c);
+
+    public void withVarargsDouble(int value, double... d);
+
+    public void withVarargsFloat(int value, float... f);
+
+    public void withVarargsInt(int value, int... i);
+
+    public void withVarargsLong(int value, long... l);
+
+    public void withVarargsShort(int value, short... s);
+}
diff --git a/tests/org/easymock/tests/InvocationTest.java b/tests/org/easymock/tests/InvocationTest.java
index 7545d48..c5de015 100644
--- a/tests/org/easymock/tests/InvocationTest.java
+++ b/tests/org/easymock/tests/InvocationTest.java
@@ -1,87 +1,119 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.Method;
-
-import org.easymock.internal.EqualsMatcher;
-import org.easymock.internal.Invocation;
-import org.junit.Before;
-import org.junit.Test;
-
-public class InvocationTest {
-
-    private Invocation call;
-
-    private Invocation equalCall;
-
-    private Invocation nonEqualCall;
-
-    @Before
-    public void setup() throws SecurityException, NoSuchMethodException {
-        Object[] arguments1 = new Object[] { "" };
-        Object[] arguments2 = new Object[] { "" };
-        Object[] arguments3 = new Object[] { "X" };
-        Method m = Object.class.getMethod("equals",
-                new Class[] { Object.class });
-        Object mock = new Object();
-        call = new Invocation(mock, m, arguments1);
-        equalCall = new Invocation(mock, m, arguments2);
-        nonEqualCall = new Invocation(mock, m, arguments3);
-    }
-
-    @Test
-    public void testEquals() {
-        assertFalse(call.equals(null));
-        assertFalse(call.equals(""));
-        assertTrue(call.equals(equalCall));
-        assertFalse(call.equals(nonEqualCall));
-    }
-
-    @Test
-    public void testHashCode() {
-        try {
-            call.hashCode();
-            fail();
-        } catch (UnsupportedOperationException expected) {
-            assertEquals("hashCode() is not implemented", expected.getMessage());
-        }
-    }
-
-    @Test
-    public void testShouldDisplayMocksToStringIfValidJavaIdentifier()
-            throws SecurityException, NoSuchMethodException {
-        class ToString {
-            private final String name;
-
-            public ToString(String name) {
-                this.name = name;
-            }
-
-            @Override
-            public String toString() {
-                return name;
-            }
-
-            public void aMethod() {
-            }
-        }
-
-        Method method = ToString.class.getMethod("aMethod", new Class[0]);
-        Invocation invocation = new Invocation(new ToString("validJavaIdentifier"),
-                method, null);
-
-        assertEquals(invocation.toString(new EqualsMatcher()),
-                "validJavaIdentifier.aMethod()");
-
-        invocation = new Invocation(new ToString("no-valid-java-identifier"),
-                method, null);
-
-        assertEquals(invocation.toString(new EqualsMatcher()), "aMethod()");
-
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+
+import org.easymock.internal.Invocation;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class InvocationTest {
+
+    private Invocation call;
+
+    private Invocation equalCall;
+
+    private Invocation nonEqualCall;
+
+    @Before
+    public void setup() throws SecurityException, NoSuchMethodException {
+        final Object[] arguments1 = new Object[] { "" };
+        final Object[] arguments2 = new Object[] { "" };
+        final Object[] arguments3 = new Object[] { "X" };
+        final Method m = Object.class.getMethod("equals", new Class[] { Object.class });
+        final Object mock = new Object();
+        call = new Invocation(mock, m, arguments1);
+        equalCall = new Invocation(mock, m, arguments2);
+        nonEqualCall = new Invocation(mock, m, arguments3);
+    }
+
+    @Test
+    public void testEquals() {
+        assertFalse(call.equals(null));
+        assertFalse(call.equals(""));
+        assertTrue(call.equals(equalCall));
+        assertFalse(call.equals(nonEqualCall));
+    }
+
+    @Test
+    public void testHashCode() {
+        try {
+            call.hashCode();
+            fail();
+        } catch (final UnsupportedOperationException expected) {
+            assertEquals("hashCode() is not implemented", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void testShouldDisplayMocksToStringIfValidJavaIdentifier() throws NoSuchMethodException {
+        class ToString {
+            private final String name;
+
+            public ToString(final String name) {
+                this.name = name;
+            }
+
+            @Override
+            public String toString() {
+                return name;
+            }
+
+            public void aMethod() {
+            }
+        }
+
+        final Method method = ToString.class.getMethod("aMethod", new Class[0]);
+        Invocation invocation = new Invocation(new ToString("validJavaIdentifier"), method, null);
+
+        assertEquals(invocation.toString(), "validJavaIdentifier.aMethod()");
+
+        invocation = new Invocation(new ToString("no-valid-java-identifier"), method, null);
+
+        assertEquals("Object.aMethod()", invocation.toString());
+
+    }
+
+    @Test
+    public void testShouldDisplayMocksToStringIfNoToStringMethod() throws NoSuchMethodException {
+        class NoToString {
+            private final String name;
+
+            public NoToString(final String name) {
+                this.name = name;
+            }
+
+            public void aMethod() {
+            }
+        }
+
+        final Method method = NoToString.class.getMethod("aMethod", new Class[0]);
+        Invocation invocation = new Invocation(new NoToString("validJavaIdentifier"), method, null);
+
+        assertEquals(invocation.toString(), "aMethod()");
+
+        invocation = new Invocation(new NoToString("no-valid-java-identifier"), method, null);
+
+        assertEquals("aMethod()", invocation.toString());
+
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/LegacyBehaviorTests.java b/tests/org/easymock/tests/LegacyBehaviorTests.java
deleted file mode 100644
index 081e6f9..0000000
--- a/tests/org/easymock/tests/LegacyBehaviorTests.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import org.easymock.MockControl;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class LegacyBehaviorTests {
-
-    @Test
-    public void throwAfterThrowable() throws IOException {
-
-        MockControl<IMethods> control = MockControl
-                .createControl(IMethods.class);
-        IMethods mock = control.getMock();
-
-        mock.throwsIOException(0);
-        control.setThrowable(new IOException());
-        control.setThrowable(new IOException(), MockControl.ONE_OR_MORE);
-
-        control.replay();
-
-        try {
-            mock.throwsIOException(0);
-            fail("IOException expected");
-        } catch (IOException expected) {
-        }
-
-        boolean exceptionOccured = true;
-        try {
-            control.verify();
-            exceptionOccured = false;
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    throwsIOException(0): expected: at least 2, actual: 1",
-                    expected.getMessage());
-        }
-
-        if (!exceptionOccured)
-            fail("exception expected");
-
-        try {
-            mock.throwsIOException(0);
-            fail("IOException expected");
-        } catch (IOException expected) {
-        }
-
-        control.verify();
-
-        try {
-            mock.throwsIOException(0);
-            fail("IOException expected");
-        } catch (IOException expected) {
-        }
-
-        control.verify();
-    }
-}
diff --git a/tests/org/easymock/tests/LimitationsTest.java b/tests/org/easymock/tests/LimitationsTest.java
new file mode 100644
index 0000000..396e24b
--- /dev/null
+++ b/tests/org/easymock/tests/LimitationsTest.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.AbstractList;
+
+import org.junit.Test;
+
+/**
+ * Test the limitations of class mocking
+ * 
+ * @author Henri Tremblay
+ */
+public class LimitationsTest {
+
+    public static class MyClass {
+        public final int foo() {
+            throw new RuntimeException();
+        }
+    }
+
+    public static class PrivateClass {
+        private PrivateClass() {
+        }
+    }
+
+    public static class NativeClass {
+        public native int foo();
+    }
+
+    public void finalClass() {
+        try {
+            createMock(String.class);
+            fail("Magic, we can mock a final class");
+        } catch (final Exception e) {
+        }
+    }
+
+    @Test
+    public void abstractClass() {
+        final Object o = createMock(AbstractList.class);
+        assertTrue(o instanceof AbstractList<?>);
+    }
+
+    @Test
+    public void mockFinalMethod() {
+        final MyClass c = createMock(MyClass.class);
+
+        try {
+            c.foo();
+            fail("Final method shouldn't be mocked");
+        } catch (final Exception e) {
+        }
+    }
+
+    @Test
+    public void privateConstructor() {
+        createMock(PrivateClass.class);
+    }
+
+    @Test
+    public void mockNativeMethod() {
+        final NativeClass mock = createMock(NativeClass.class);
+        expect(mock.foo()).andReturn(1);
+        replay(mock);
+        assertEquals(1, mock.foo());
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/MatchableArgumentsTest.java b/tests/org/easymock/tests/MatchableArgumentsTest.java
index 214b9d8..6955350 100644
--- a/tests/org/easymock/tests/MatchableArgumentsTest.java
+++ b/tests/org/easymock/tests/MatchableArgumentsTest.java
@@ -1,45 +1,56 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.Method;
-
-import org.easymock.internal.ExpectedInvocation;
-import org.easymock.internal.Invocation;
-import org.junit.Before;
-import org.junit.Test;
-
-public class MatchableArgumentsTest {
-
-    private Object[] arguments;
-
-    private Object[] arguments2;
-
-    @Before
-    public void setup() {
-        arguments = new Object[] { "" };
-        arguments2 = new Object[] { "", "" };
-    }
-
-    @Test
-    public void testEquals() throws SecurityException, NoSuchMethodException {
-        Method toPreventNullPointerExceptionm = Object.class.getMethod(
-                "toString", new Class[] {});
-
-        Object mock = new Object();
-
-        ExpectedInvocation matchableArguments = new ExpectedInvocation(
-                new Invocation(mock, toPreventNullPointerExceptionm, arguments),
-                null);
-        ExpectedInvocation nonEqualMatchableArguments = new ExpectedInvocation(
-                new Invocation(mock, toPreventNullPointerExceptionm, arguments2),
-                null);
-
-        assertFalse(matchableArguments.equals(null));
-        assertFalse(matchableArguments.equals(nonEqualMatchableArguments));
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+
+import org.easymock.internal.ExpectedInvocation;
+import org.easymock.internal.Invocation;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class MatchableArgumentsTest {
+
+    private Object[] arguments;
+
+    private Object[] arguments2;
+
+    @Before
+    public void setup() {
+        arguments = new Object[] { "" };
+        arguments2 = new Object[] { "", "" };
+    }
+
+    @Test
+    public void testEquals() throws SecurityException, NoSuchMethodException {
+        final Method toPreventNullPointerExceptionm = Object.class.getMethod("toString", new Class[] {});
+
+        final Object mock = new Object();
+
+        final ExpectedInvocation matchableArguments = new ExpectedInvocation(new Invocation(mock,
+                toPreventNullPointerExceptionm, arguments), null);
+        final ExpectedInvocation nonEqualMatchableArguments = new ExpectedInvocation(new Invocation(mock,
+                toPreventNullPointerExceptionm, arguments2), null);
+
+        assertFalse(matchableArguments.equals(null));
+        assertFalse(matchableArguments.equals(nonEqualMatchableArguments));
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/MethodSerializationWrapperTest.java b/tests/org/easymock/tests/MethodSerializationWrapperTest.java
index 592a7f8..a84f187 100644
--- a/tests/org/easymock/tests/MethodSerializationWrapperTest.java
+++ b/tests/org/easymock/tests/MethodSerializationWrapperTest.java
@@ -1,24 +1,44 @@
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.Method;
-
-import org.easymock.internal.MethodSerializationWrapper;
-import org.junit.Test;
-
-public class MethodSerializationWrapperTest {
-
-    public static class A {
-        public void foo(String s, int i, String[] sArray, int[] iArray, String...varargs ) {            
-        }
-    }
-    
-    @Test
-    public void testGetMethod() throws Exception {
-        Method foo = A.class.getMethod("foo", String.class, Integer.TYPE, String[].class, int[].class, String[].class);
-        MethodSerializationWrapper wrapper = new MethodSerializationWrapper(foo);
-        assertEquals(foo, wrapper.getMethod());
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+
+import org.easymock.internal.MethodSerializationWrapper;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class MethodSerializationWrapperTest {
+
+    public static class A {
+        public void foo(final String s, final int i, final String[] sArray, final int[] iArray,
+                final String... varargs) {
+        }
+    }
+
+    @Test
+    public void testGetMethod() throws Exception {
+        final Method foo = A.class.getMethod("foo", String.class, Integer.TYPE, String[].class, int[].class,
+                String[].class);
+        final MethodSerializationWrapper wrapper = new MethodSerializationWrapper(foo);
+        assertEquals(foo, wrapper.getMethod());
+    }
+
+}
diff --git a/tests/org/easymock/tests/MockClassControlTest.java b/tests/org/easymock/tests/MockClassControlTest.java
new file mode 100644
index 0000000..291c20b
--- /dev/null
+++ b/tests/org/easymock/tests/MockClassControlTest.java
@@ -0,0 +1,168 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests of MockClassControl basic functionnalities
+ * 
+ * @author Henri Tremblay
+ * @author OFFIS, Tammo Freese
+ */
+public class MockClassControlTest {
+
+    /**
+     * Class that will be mocked. The methods defined in it are there just to
+     * make sure they are correctly overloaded by the mock.
+     */
+    public static class ClassToMock {
+
+    }
+
+    /**
+     * Same as ClassToMock except that the methods with a standard behavior
+     * provided by the mock are overloaded. We expect the standard behavior to
+     * still be called.
+     */
+    public static class ClassToMockWithOverload {
+
+        @Override
+        public boolean equals(final Object o) {
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return -1;
+        }
+
+        @Override
+        public String toString() {
+            return "super";
+        }
+    }
+
+    public static class ClassWithAnotherOverload extends ClassToMockWithOverload {
+
+        @Override
+        public String toString() {
+            return "super.super";
+        }
+    }
+
+    public static class ClassWithFinalize {
+
+        @Override
+        public void finalize() {
+        }
+    }
+
+    private Object mock;
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mock = null;
+    }
+
+    private void initMock(final Class<?> toMock) {
+        mock = createMock(toMock);
+    }
+
+    @Test
+    public void testEquals() {
+        testEquals(ClassToMock.class);
+    }
+
+    @Test
+    public void testEquals_WithOverload() {
+        testEquals(ClassToMockWithOverload.class);
+    }
+
+    /**
+     * Make sure that a mock is equals to itself
+     */
+    private void testEquals(final Class<?> toMock) {
+        initMock(toMock);
+        assertEquals(mock, mock);
+        replay(mock);
+        assertEquals(mock, mock);
+    }
+
+    @Test
+    public void testHashCode() {
+        testHashCode(ClassToMock.class);
+    }
+
+    @Test
+    public void testHashCode_WithOverload() {
+        testHashCode(ClassToMockWithOverload.class);
+    }
+
+    /**
+     * Make sure the hashCode doesn't need to be recorded and that it stays the
+     * same after the replay
+     */
+    private void testHashCode(final Class<?> toMock) {
+        initMock(toMock);
+        final int code = mock.hashCode();
+        replay(mock);
+        assertEquals(code, mock.hashCode());
+    }
+
+    @Test
+    public void testToString() {
+        testToString(ClassToMock.class);
+    }
+
+    @Test
+    public void testToString_WithOverload() {
+        testToString(ClassToMockWithOverload.class);
+    }
+
+    @Test
+    public void testToString_WithTwoOverload() {
+        testToString(ClassWithAnotherOverload.class);
+    }
+
+    /**
+     * Check that the toString is the EasyMock one giving the mocked class
+     */
+    private void testToString(final Class<?> toMock) {
+        initMock(toMock);
+        final String expectedValue = "EasyMock for " + toMock.toString();
+        assertEquals(expectedValue, mock.toString());
+        replay(mock);
+        assertEquals(expectedValue, mock.toString());
+    }
+
+    @Test
+    public void testFinalize_AreIgnored() {
+        final ClassWithFinalize mock = createMock(ClassWithFinalize.class);
+        replay(mock);
+        mock.finalize();
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/MockNameTest.java b/tests/org/easymock/tests/MockNameTest.java
index 0e2614d..b3c1a3e 100644
--- a/tests/org/easymock/tests/MockNameTest.java
+++ b/tests/org/easymock/tests/MockNameTest.java
@@ -1,24 +1,35 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class MockNameTest {
-
-    private MockControl<IMethods> control;
-
-    @Test
-    public void defaultName() {
-        control = MockControl.createControl(IMethods.class);
-        String expected = "EasyMock for " + IMethods.class.toString();
-        String actual = control.getMock().toString();
-        assertEquals(expected, actual);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class MockNameTest {
+
+    @Test
+    public void defaultName() {
+        final IMethods mock = createMock(IMethods.class);
+        final String expected = "EasyMock for " + IMethods.class.toString();
+        final String actual = mock.toString();
+        assertEquals(expected, actual);
+    }
+}
diff --git a/tests/org/easymock/tests/MockTypeTest.java b/tests/org/easymock/tests/MockTypeTest.java
new file mode 100644
index 0000000..496e08b
--- /dev/null
+++ b/tests/org/easymock/tests/MockTypeTest.java
@@ -0,0 +1,104 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import org.easymock.EasyMock;
+import org.easymock.EasyMockSupport;
+import org.easymock.IMockBuilder;
+import org.easymock.MockType;
+import org.easymock.internal.MocksControl;
+import org.junit.Test;
+
+/**
+ * Test mocks create with a MockType
+ *  
+ * @author Henri Tremblay
+ */
+public class MockTypeTest {
+
+    private final EasyMockSupport support = new EasyMockSupport();
+
+    private final IMockBuilder<MockTypeTest> builder = EasyMock.createMockBuilder(MockTypeTest.class);
+
+    @Test
+    public void fromEasyMockClass() {
+        final IMethods mock = EasyMock.createMock(MockType.STRICT, IMethods.class);
+        final MockType type = MocksControl.getControl(mock).getType();
+        assertEquals(MockType.STRICT, type);
+        assertEquals("EasyMock for interface " + IMethods.class.getName(), mock.toString());
+    }
+
+    @Test
+    public void fromEasyMockClassWithName() {
+        final IMethods mock = EasyMock.createMock("test", MockType.STRICT, IMethods.class);
+        final MockType type = MocksControl.getControl(mock).getType();
+        assertEquals(MockType.STRICT, type);
+        assertEquals("test", mock.toString());
+    }
+
+    @Test
+    public void fromEasyMockControlWithName() {
+        final MocksControl ctrl = (MocksControl) EasyMock.createControl(MockType.STRICT);
+        assertEquals(MockType.STRICT, ctrl.getType());
+    }
+
+    @Test
+    public void fromEasyMockSupportClass() {
+        final IMethods mock = support.createMock(MockType.STRICT, IMethods.class);
+        final MockType type = MocksControl.getControl(mock).getType();
+        assertEquals(MockType.STRICT, type);
+        assertEquals("EasyMock for interface " + IMethods.class.getName(), mock.toString());
+    }
+
+    @Test
+    public void fromEasyMockSupportClassWithName() {
+        final IMethods mock = support.createMock("test", MockType.STRICT, IMethods.class);
+        final MockType type = MocksControl.getControl(mock).getType();
+        assertEquals(MockType.STRICT, type);
+        assertEquals("test", mock.toString());
+    }
+
+    @Test
+    public void fromEasyMockSupportControlWithName() {
+        final MocksControl ctrl = (MocksControl) support.createControl(MockType.STRICT);
+        assertEquals(MockType.STRICT, ctrl.getType());
+    }
+
+    // The two following tests are showing a strange behavior. The toString doesn't return the
+    // default EasyMock implementation. I won't change it right now but it doesn't feel right
+    @Test
+    public void fromMockBuilderClass() {
+        final MockTypeTest mock = builder.addMockedMethod("toString").createMock(MockType.STRICT);
+        final MockType type = MocksControl.getControl(mock).getType();
+        assertEquals(MockType.STRICT, type);
+        assertEquals("EasyMock for class " + MockTypeTest.class.getName(), mock.toString());
+    }
+
+    @Test
+    public void fromMockBuilderClassWithName() {
+        final MockTypeTest mock = builder.addMockedMethod("toString").createMock("test", MockType.STRICT);
+        final MockType type = MocksControl.getControl(mock).getType();
+        assertEquals(MockType.STRICT, type);
+        assertEquals("test", mock.toString());
+    }
+
+    @Override
+    public String toString() {
+        return "this is a toString";
+    }
+}
diff --git a/tests/org/easymock/tests/MockingTest.java b/tests/org/easymock/tests/MockingTest.java
new file mode 100644
index 0000000..9867a1e
--- /dev/null
+++ b/tests/org/easymock/tests/MockingTest.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.easymock.MockType;
+import org.easymock.internal.MocksControl;
+import org.junit.Test;
+
+/**
+ * Test all kind of mocking making sure the partial mocking and interface works
+ * and that to correct behavior is given.
+ * 
+ * @author Henri Tremblay
+ */
+public class MockingTest {
+
+    public static class ClassToMock {
+        public int foo() {
+            return 10;
+        }
+
+        public int method() {
+            return 20;
+        }
+    }
+
+    /**
+     * Make sure one mock is not interacting with another
+     */
+    @Test
+    public void testTwoMocks() {
+        final ClassToMock transition1 = createMock(ClassToMock.class);
+        final ClassToMock transition2 = createMock(ClassToMock.class);
+
+        // Should have two different callbacks
+        assertNotSame(MocksControl.getInvocationHandler(transition2),
+                MocksControl.getInvocationHandler(transition1));
+
+        transition2.foo();
+        transition1.foo();
+    }
+
+    @Test
+    public void testInterfaceMocking() {
+        checkInterfaceMock(createMock(List.class), MockType.DEFAULT);
+    }
+
+    @Test
+    public void testNiceInterfaceMocking() {
+        checkInterfaceMock(createNiceMock(List.class), MockType.NICE);
+    }
+
+    @Test
+    public void testStrictInterfaceMocking() {
+        checkInterfaceMock(createStrictMock(List.class), MockType.STRICT);
+    }
+
+    @Test
+    public void testClassMocking() {
+        checkClassMocking(createMock(ClassToMock.class), MockType.DEFAULT);
+    }
+
+    @Test
+    public void testStrictClassMocking() {
+        checkClassMocking(createStrictMock(ClassToMock.class), MockType.STRICT);
+    }
+
+    @Test
+    public void testNiceClassMocking() {
+        checkClassMocking(createNiceMock(ClassToMock.class), MockType.NICE);
+    }
+
+    private void checkInterfaceMock(final Object mock, final MockType behavior) {
+        checkBehavior(mock, behavior);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testPartialClassMocking() {
+        final ClassToMock mock = createMock(ClassToMock.class, getMethod());
+        checkPartialClassMocking(mock, MockType.DEFAULT);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testStrictPartialClassMocking() {
+        final ClassToMock mock = createStrictMock(ClassToMock.class, getMethod());
+        checkPartialClassMocking(mock, MockType.STRICT);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testNicePartialClassMocking() {
+        final ClassToMock mock = createNiceMock(ClassToMock.class, getMethod());
+        checkPartialClassMocking(mock, MockType.NICE);
+    }
+
+    private void checkPartialClassMocking(final ClassToMock mock, final MockType behavior) {
+        checkClassMocking(mock, behavior);
+        assertEquals(10, mock.foo());
+        expect(mock.method()).andReturn(30);
+        replay(mock);
+        assertEquals(10, mock.foo());
+        assertEquals(30, mock.method());
+        verify(mock);
+    }
+
+    private void checkClassMocking(final Object mock, final MockType behavior) {
+        checkBehavior(mock, behavior);
+    }
+
+    private void checkBehavior(final Object mock, final MockType behavior) {
+        assertEquals(behavior, extractBehavior(mock));
+    }
+
+    private MockType extractBehavior(final Object mock) {
+        final MocksControl ctrl = MocksControl.getControl(mock);
+        return ctrl.getType();
+    }
+
+    private Method[] getMethod() {
+        try {
+            return new Method[] { ClassToMock.class.getDeclaredMethod("method", (Class[]) null) };
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/NiceMockControlLongCompatibleReturnValueTest.java b/tests/org/easymock/tests/NiceMockControlLongCompatibleReturnValueTest.java
index 0a5311b..4cc8bcf 100644
--- a/tests/org/easymock/tests/NiceMockControlLongCompatibleReturnValueTest.java
+++ b/tests/org/easymock/tests/NiceMockControlLongCompatibleReturnValueTest.java
@@ -1,56 +1,66 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class NiceMockControlLongCompatibleReturnValueTest {
-
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createNiceControl(IMethods.class);
-        mock = control.getMock();
-        control.replay();
-    }
-
-    @Test
-    public void byteReturningValue() {
-        assertEquals((byte) 0, mock.byteReturningMethod(12));
-        control.verify();
-    }
-
-    @Test
-    public void shortReturningValue() {
-        assertEquals((short) 0, mock.shortReturningMethod(12));
-        control.verify();
-    }
-
-    @Test
-    public void charReturningValue() {
-        assertEquals((char) 0, mock.charReturningMethod(12));
-        control.verify();
-    }
-
-    @Test
-    public void intReturningValue() {
-        assertEquals(0, mock.intReturningMethod(12));
-        control.verify();
-    }
-
-    @Test
-    public void longReturningValue() {
-        assertEquals((long) 0, mock.longReturningMethod(12));
-        control.verify();
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class NiceMockControlLongCompatibleReturnValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createNiceMock(IMethods.class);
+        replay(mock);
+    }
+
+    @Test
+    public void byteReturningValue() {
+        assertEquals((byte) 0, mock.byteReturningMethod(12));
+        verify(mock);
+    }
+
+    @Test
+    public void shortReturningValue() {
+        assertEquals((short) 0, mock.shortReturningMethod(12));
+        verify(mock);
+    }
+
+    @Test
+    public void charReturningValue() {
+        assertEquals((char) 0, mock.charReturningMethod(12));
+        verify(mock);
+    }
+
+    @Test
+    public void intReturningValue() {
+        assertEquals(0, mock.intReturningMethod(12));
+        verify(mock);
+    }
+
+    @Test
+    public void longReturningValue() {
+        assertEquals(0, mock.longReturningMethod(12));
+        verify(mock);
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/NiceMockControlTest.java b/tests/org/easymock/tests/NiceMockControlTest.java
index 073c1a2..a08a27d 100644
--- a/tests/org/easymock/tests/NiceMockControlTest.java
+++ b/tests/org/easymock/tests/NiceMockControlTest.java
@@ -1,49 +1,60 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class NiceMockControlTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createNiceControl(IMethods.class);
-        mock = control.getMock();
-        control.replay();
-    }
-
-    @Test
-    public void defaultReturnValueBoolean() {
-        assertEquals(false, mock.booleanReturningMethod(12));
-        control.verify();
-    }
-
-    @Test
-    public void defaultReturnValueFloat() {
-        assertEquals(0.0f, mock.floatReturningMethod(12), 0.0f);
-        control.verify();
-    }
-
-    @Test
-    public void defaultReturnValueDouble() {
-        assertEquals(0.0d, mock.doubleReturningMethod(12), 0.0d);
-        control.verify();
-    }
-
-    @Test
-    public void defaultReturnValueObject() {
-        assertEquals(null, mock.objectReturningMethod(12));
-        control.verify();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class NiceMockControlTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createNiceMock(IMethods.class);
+        replay(mock);
+    }
+
+    @Test
+    public void defaultReturnValueBoolean() {
+        assertEquals(false, mock.booleanReturningMethod(12));
+        verify(mock);
+    }
+
+    @Test
+    public void defaultReturnValueFloat() {
+        assertEquals(0.0f, mock.floatReturningMethod(12), 0.0f);
+        verify(mock);
+    }
+
+    @Test
+    public void defaultReturnValueDouble() {
+        assertEquals(0.0d, mock.doubleReturningMethod(12), 0.0d);
+        verify(mock);
+    }
+
+    @Test
+    public void defaultReturnValueObject() {
+        assertEquals(null, mock.objectReturningMethod(12));
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/ObjectMethodsTest.java b/tests/org/easymock/tests/ObjectMethodsTest.java
index 83f9928..d6a378d 100644
--- a/tests/org/easymock/tests/ObjectMethodsTest.java
+++ b/tests/org/easymock/tests/ObjectMethodsTest.java
@@ -1,81 +1,90 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.lang.reflect.Method;
-
-import org.easymock.MockControl;
-import org.easymock.internal.ObjectMethodsFilter;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class ObjectMethodsTest {
-    private MockControl<EmptyInterface> control;
-
-    private EmptyInterface mock;
-
-    private interface EmptyInterface {
-    }
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(EmptyInterface.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void equalsBeforeActivation() {
-        assertEquals(mock, mock);
-        assertTrue(!mock.equals(null));
-    }
-
-    @Test
-    public void equalsAfterActivation() {
-        control.replay();
-        assertEquals(mock, mock);
-        assertTrue(!mock.equals(null));
-    }
-
-    @Test
-    public void testHashCode() {
-        int hashCodeBeforeActivation = mock.hashCode();
-        control.replay();
-        int hashCodeAfterActivation = mock.hashCode();
-        assertEquals(hashCodeBeforeActivation, hashCodeAfterActivation);
-    }
-
-    @Test
-    public void toStringBeforeActivation() {
-        assertEquals("EasyMock for " + EmptyInterface.class.toString(), mock
-                .toString());
-    }
-
-    @Test
-    public void toStringAfterActivation() {
-        control.replay();
-        assertEquals("EasyMock for " + EmptyInterface.class.toString(), mock
-                .toString());
-    }
-
-    private static class MockedClass {
-    }
-
-    private static class DummyProxy extends MockedClass {
-    }
-
-    // if the class is no Proxy, ObjectMethodFilter should use the
-    // superclasses' name. This is needed for the class extension.
-    @Test
-    public void toStringForClasses() throws Throwable {
-        ObjectMethodsFilter filter = new ObjectMethodsFilter(Object.class, null, null);
-        Method toString = Object.class.getMethod("toString", new Class[0]);
-        assertEquals("EasyMock for " + MockedClass.class.toString(), filter
-                .invoke(new DummyProxy(), toString, new Object[0]));
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+
+import org.easymock.internal.ObjectMethodsFilter;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ObjectMethodsTest {
+
+    private EmptyInterface mock;
+
+    private interface EmptyInterface {
+    }
+
+    @Before
+    public void setup() {
+        mock = createMock(EmptyInterface.class);
+    }
+
+    @Test
+    public void equalsBeforeActivation() {
+        assertEquals(mock, mock);
+        assertTrue(!mock.equals(null));
+    }
+
+    @Test
+    public void equalsAfterActivation() {
+        replay(mock);
+        assertEquals(mock, mock);
+        assertTrue(!mock.equals(null));
+    }
+
+    @Test
+    public void testHashCode() {
+        final int hashCodeBeforeActivation = mock.hashCode();
+        replay(mock);
+        final int hashCodeAfterActivation = mock.hashCode();
+        assertEquals(hashCodeBeforeActivation, hashCodeAfterActivation);
+    }
+
+    @Test
+    public void toStringBeforeActivation() {
+        assertEquals("EasyMock for " + EmptyInterface.class.toString(), mock.toString());
+    }
+
+    @Test
+    public void toStringAfterActivation() {
+        replay(mock);
+        assertEquals("EasyMock for " + EmptyInterface.class.toString(), mock.toString());
+    }
+
+    private static class MockedClass {
+    }
+
+    private static class DummyProxy extends MockedClass {
+    }
+
+    // if the class is no Proxy, ObjectMethodFilter should use the
+    // superclasses' name. This is needed for the class extension.
+    @Test
+    public void toStringForClasses() throws Throwable {
+        final ObjectMethodsFilter filter = new ObjectMethodsFilter(Object.class, null, null);
+        final Method toString = Object.class.getMethod("toString", new Class[0]);
+        assertEquals("EasyMock for " + MockedClass.class.toString(), filter.invoke(new DummyProxy(),
+                toString, new Object[0]));
+    }
+
+}
diff --git a/tests/org/easymock/tests/RecordStateInvalidDefaultReturnValueTest.java b/tests/org/easymock/tests/RecordStateInvalidDefaultReturnValueTest.java
index 989ce95..e055c08 100644
--- a/tests/org/easymock/tests/RecordStateInvalidDefaultReturnValueTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidDefaultReturnValueTest.java
@@ -1,91 +1,45 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidDefaultReturnValueTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void setInvalidDefaultBooleanReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setDefaultReturnValue(false);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidDefaultLongReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setDefaultReturnValue((long) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidDefaultFloatReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setDefaultReturnValue((float) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidDefaultDoubleReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setDefaultReturnValue((double) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidObjectDefaultReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setDefaultReturnValue(new Object());
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setDefaultReturnValueWithoutMethodCall() {
-        try {
-            control.setDefaultReturnValue(new Object());
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals(
-                    "method call on the mock needed before setting default return value",
-                    e.getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidDefaultReturnValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void setInvalidStubReturnValue() {
+        try {
+            expect((Object) mock.oneArg(false)).andStubReturn(false);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException e) {
+            assertEquals("incompatible return value type", e.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/RecordStateInvalidDefaultThrowableTest.java b/tests/org/easymock/tests/RecordStateInvalidDefaultThrowableTest.java
index be25d30..dacb4b9 100644
--- a/tests/org/easymock/tests/RecordStateInvalidDefaultThrowableTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidDefaultThrowableTest.java
@@ -1,81 +1,74 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidDefaultThrowableTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    private class CheckedException extends Exception {
-        private static final long serialVersionUID = 1L;
-    }
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void throwNull() {
-        mock.throwsNothing(false);
-        try {
-            control.setDefaultThrowable(null);
-            fail("NullPointerException expected");
-        } catch (NullPointerException expected) {
-            assertEquals("null cannot be thrown", expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void throwCheckedExceptionWhereNoCheckedExceptionIsThrown() {
-        mock.throwsNothing(false);
-        try {
-            control.setDefaultThrowable(new CheckedException());
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("last method called on mock cannot throw "
-                    + this.getClass().getName() + "$CheckedException", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void throwWrongCheckedException() throws IOException {
-        mock.throwsIOException(0);
-        try {
-            control.setDefaultThrowable(new CheckedException());
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("last method called on mock cannot throw "
-                    + this.getClass().getName() + "$CheckedException", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setDefaultThrowableWithoutMethodCall() throws IOException {
-        try {
-            control.setDefaultThrowable(new RuntimeException());
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default Throwable",
-                    expected.getMessage());
-        }
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidDefaultThrowableTest {
+
+    private IMethods mock;
+
+    private class CheckedException extends Exception {
+        private static final long serialVersionUID = 1L;
+    }
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void throwNull() {
+        try {
+            expect(mock.throwsNothing(false)).andStubThrow(null);
+            fail("NullPointerException expected");
+        } catch (final NullPointerException expected) {
+            assertEquals("null cannot be thrown", expected.getMessage());
+        }
+
+    }
+
+    @Test
+    public void throwCheckedExceptionWhereNoCheckedExceptionIsThrown() {
+        try {
+            expect(mock.throwsNothing(false)).andStubThrow(new CheckedException());
+            fail("IllegalArgumentException expected");
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("last method called on mock cannot throw " + this.getClass().getName()
+                    + "$CheckedException", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void throwWrongCheckedException() throws IOException {
+        try {
+            expect(mock.throwsIOException(0)).andStubThrow(new CheckedException());
+            fail("IllegalArgumentException expected");
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("last method called on mock cannot throw " + this.getClass().getName()
+                    + "$CheckedException", expected.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/RecordStateInvalidMatcherTest.java b/tests/org/easymock/tests/RecordStateInvalidMatcherTest.java
deleted file mode 100644
index 68263cf..0000000
--- a/tests/org/easymock/tests/RecordStateInvalidMatcherTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidMatcherTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void setMatcherBeforeCallingMethods() {
-        try {
-            control.setMatcher(MockControl.ARRAY_MATCHER);
-            fail();
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting matcher",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setMatcherTwice() {
-        mock.simpleMethod();
-        control.setMatcher(MockControl.ARRAY_MATCHER);
-        try {
-            control.setMatcher(MockControl.EQUALS_MATCHER);
-            fail();
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "for method simpleMethod(), a matcher has already been set",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setMatcherTwice2() {
-        mock.simpleMethodWithArgument("");
-        control.setMatcher(MockControl.ARRAY_MATCHER);
-        try {
-            control.setMatcher(MockControl.EQUALS_MATCHER);
-            fail();
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "for method simpleMethodWithArgument(...), a matcher has already been set",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setSameMatcherTwice() {
-        mock.simpleMethod();
-        control.setMatcher(MockControl.ARRAY_MATCHER);
-        try {
-            control.setMatcher(MockControl.ARRAY_MATCHER);
-        } catch (IllegalStateException unexpected) {
-            fail("setting the same matcher should work");
-        }
-    }
-}
diff --git a/tests/org/easymock/tests/RecordStateInvalidRangeTest.java b/tests/org/easymock/tests/RecordStateInvalidRangeTest.java
index 3633c29..608b009 100644
--- a/tests/org/easymock/tests/RecordStateInvalidRangeTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidRangeTest.java
@@ -1,74 +1,94 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidRangeTest {
-
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setUp() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void setOpenCallCountTwice() {
-        mock.simpleMethod();
-        control.setVoidCallable(MockControl.ONE_OR_MORE);
-        try {
-            control.setVoidCallable(MockControl.ONE_OR_MORE);
-            fail();
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "last method called on mock already has a non-fixed count set.",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setIllegalMinimumCount() {
-        mock.simpleMethod();
-        int NEGATIVE = -1;
-        try {
-            control.setVoidCallable(NEGATIVE, 2);
-            fail();
-        } catch (IllegalArgumentException expected) {
-            assertEquals("minimum must be >= 0", expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setIllegalMaximumCount() {
-        mock.simpleMethod();
-        int NON_POSITIVE = 0;
-        try {
-            control.setVoidCallable(0, NON_POSITIVE);
-            fail();
-        } catch (IllegalArgumentException expected) {
-            assertEquals("maximum must be >= 1", expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setMinimumBiggerThanMaximum() {
-        mock.simpleMethod();
-        try {
-            control.setVoidCallable(4, 3);
-            fail();
-        } catch (IllegalArgumentException expected) {
-            assertEquals("minimum must be <= maximum", expected.getMessage());
-        }
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidRangeTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void setOpenCallCountTwice() {
+        mock.simpleMethod();
+        try {
+            expectLastCall().atLeastOnce().atLeastOnce();
+            fail();
+        } catch (final IllegalStateException expected) {
+            assertEquals("last method called on mock already has a non-fixed count set.", expected
+                    .getMessage());
+        }
+    }
+
+    @Test
+    public void setCloseCallAfterOpenOne() {
+        mock.simpleMethod();
+        try {
+            expectLastCall().atLeastOnce().once();
+            fail();
+        } catch (final IllegalStateException expected) {
+            assertEquals("last method called on mock already has a non-fixed count set.", expected
+                    .getMessage());
+        }
+    }
+
+    @Test
+    public void setIllegalMinimumCount() {
+        mock.simpleMethod();
+        final int NEGATIVE = -1;
+        try {
+            expectLastCall().times(NEGATIVE, 2);
+            fail();
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("minimum must be >= 0", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void setIllegalMaximumCount() {
+        mock.simpleMethod();
+        final int NON_POSITIVE = 0;
+        try {
+            expectLastCall().times(0, NON_POSITIVE);
+            fail();
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("maximum must be >= 1", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void setMinimumBiggerThanMaximum() {
+        mock.simpleMethod();
+        try {
+            expectLastCall().times(4, 3);
+            fail();
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("minimum must be <= maximum", expected.getMessage());
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/RecordStateInvalidReturnValueTest.java b/tests/org/easymock/tests/RecordStateInvalidReturnValueTest.java
index b758398..5a0940d 100644
--- a/tests/org/easymock/tests/RecordStateInvalidReturnValueTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidReturnValueTest.java
@@ -1,147 +1,67 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidReturnValueTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void setInvalidBooleanReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(false);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-
-    }
-
-    @Test
-    public void setInvalidLongReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((long) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidFloatReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((float) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidDoubleReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((double) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidObjectReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(new Object());
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidBooleanReturnValueCount() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(false, 3);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-
-    }
-
-    @Test
-    public void setInvalidLongReturnValueCount() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((long) 0, 3);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidFloatReturnValueCount() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((float) 0, 3);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidDoubleReturnValueCount() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((double) 0, 3);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setInvalidObjectReturnValueCount() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(new Object(), 3);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("incompatible return value type", e.getMessage());
-        }
-    }
-
-    @Test
-    public void setReturnValueForVoidMethod() {
-        mock.simpleMethod();
-        try {
-            control.setReturnValue(null);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("void method cannot return a value", e.getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidReturnValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void setInvalidBooleanReturnValue() {
+        try {
+            expect((Object) mock.oneArg(false)).andReturn(false);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException e) {
+            assertEquals("incompatible return value type", e.getMessage());
+        }
+
+    }
+
+    @Test
+    public void setReturnValueForVoidMethod() {
+        mock.simpleMethod();
+        try {
+            expectLastCall().andReturn(null);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException e) {
+            assertEquals("void method cannot return a value", e.getMessage());
+        }
+    }
+
+    @Test
+    public void nullForPrimitive() {
+        try {
+            expect(mock.longReturningMethod(4)).andReturn(null);
+            fail("null not allowed");
+        } catch (final IllegalStateException e) {
+            assertEquals("can't return null for a method returning a primitive type", e.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/RecordStateInvalidStateChangeTest.java b/tests/org/easymock/tests/RecordStateInvalidStateChangeTest.java
index c3ad494..d81addb 100644
--- a/tests/org/easymock/tests/RecordStateInvalidStateChangeTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidStateChangeTest.java
@@ -1,66 +1,74 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.easymock.internal.RecordState;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidStateChangeTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void activateWithoutReturnValue() {
-        mock.oneArg(false);
-        try {
-            control.replay();
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals(
-                    "missing behavior definition for the preceeding method call oneArg(false)",
-                    e.getMessage());
-            assertTrue("stack trace must be cut", Util.getStackTrace(e)
-                    .indexOf(RecordState.class.getName()) == -1);
-        }
-    }
-
-    @Test
-    public void secondCallWithoutReturnValue() {
-        mock.oneArg(false);
-        try {
-            mock.oneArg(false);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals(
-                    "missing behavior definition for the preceeding method call oneArg(false)",
-                    e.getMessage());
-            assertTrue("stack trace must be cut", Util.getStackTrace(e)
-                    .indexOf(RecordState.class.getName()) == -1);
-        }
-    }
-
-    @Test
-    public void verifyWithoutActivation() {
-        try {
-            control.verify();
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException e) {
-            assertEquals("calling verify is not allowed in record state", e
-                    .getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.internal.RecordState;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidStateChangeTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void activateWithoutReturnValue() {
+        expect(mock.oneArg(false));
+        try {
+            replay(mock);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException e) {
+            assertEquals("missing behavior definition for the preceding method call:\nIMethods.oneArg(false)"
+                    + "\nUsage is: expect(a.foo()).andXXX()", e.getMessage());
+            assertTrue("stack trace must be cut",
+                    Util.getStackTrace(e).indexOf(RecordState.class.getName()) == -1);
+        }
+    }
+
+    @Test
+    public void secondCallWithoutReturnValue() {
+        mock.oneArg(false);
+        try {
+            mock.oneArg(false);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException e) {
+            assertEquals("missing behavior definition for the preceding method call:\nIMethods.oneArg(false)"
+                    + "\nUsage is: expect(a.foo()).andXXX()", e.getMessage());
+            assertTrue("stack trace must be cut",
+                    Util.getStackTrace(e).indexOf(RecordState.class.getName()) == -1);
+        }
+    }
+
+    @Test
+    public void verifyWithoutActivation() {
+        try {
+            verify(mock);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException e) {
+            assertEquals("calling verify is not allowed in record state", e.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/RecordStateInvalidThrowableTest.java b/tests/org/easymock/tests/RecordStateInvalidThrowableTest.java
index 64d1419..a763c6c 100644
--- a/tests/org/easymock/tests/RecordStateInvalidThrowableTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidThrowableTest.java
@@ -1,81 +1,77 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidThrowableTest {
-
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    private class CheckedException extends Exception {
-        private static final long serialVersionUID = 1L;
-    }
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void throwNull() {
-        mock.throwsNothing(false);
-        try {
-            control.setThrowable(null);
-            fail("NullPointerException expected");
-        } catch (NullPointerException expected) {
-            assertEquals("null cannot be thrown", expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void throwCheckedExceptionWhereNoCheckedExceptionIsThrown() {
-        mock.throwsNothing(false);
-        try {
-            control.setThrowable(new CheckedException());
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("last method called on mock cannot throw "
-                    + CheckedException.class.getName(), expected.getMessage());
-        }
-    }
-
-    @Test
-    public void throwWrongCheckedException() throws IOException {
-        mock.throwsIOException(0);
-        try {
-            control.setThrowable(new CheckedException());
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("last method called on mock cannot throw "
-                    + CheckedException.class.getName(), expected.getMessage());
-        }
-    }
-
-    @Test
-    public void throwAfterThrowable() throws IOException {
-        mock.throwsIOException(0);
-        control.setThrowable(new IOException(), MockControl.ONE_OR_MORE);
-        try {
-            control.setThrowable(new IOException());
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "last method called on mock already has a non-fixed count set.",
-                    expected.getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidThrowableTest {
+
+    private IMethods mock;
+
+    private class CheckedException extends Exception {
+        private static final long serialVersionUID = 1L;
+    }
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void throwNull() {
+        mock.throwsNothing(false);
+        try {
+            expectLastCall().andThrow(null);
+            fail("NullPointerException expected");
+        } catch (final NullPointerException expected) {
+            assertEquals("null cannot be thrown", expected.getMessage());
+        }
+
+    }
+
+    @Test
+    public void throwCheckedExceptionWhereNoCheckedExceptionIsThrown() {
+        mock.throwsNothing(false);
+        try {
+            expectLastCall().andThrow(new CheckedException());
+            fail("IllegalArgumentException expected");
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("last method called on mock cannot throw " + CheckedException.class.getName(),
+                    expected.getMessage());
+        }
+    }
+
+    @Test
+    public void throwWrongCheckedException() throws IOException {
+        mock.throwsIOException(0);
+        try {
+            expectLastCall().andThrow(new CheckedException());
+            fail("IllegalArgumentException expected");
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("last method called on mock cannot throw " + CheckedException.class.getName(),
+                    expected.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/RecordStateInvalidUsageTest.java b/tests/org/easymock/tests/RecordStateInvalidUsageTest.java
index 0438e94..bb3f3d9 100644
--- a/tests/org/easymock/tests/RecordStateInvalidUsageTest.java
+++ b/tests/org/easymock/tests/RecordStateInvalidUsageTest.java
@@ -1,157 +1,65 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class RecordStateInvalidUsageTest {
-
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void setReturnValueWithoutMethodCall() {
-        try {
-            control.setReturnValue(false);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setExpectedVoidCallCountWithoutMethodCall() {
-        try {
-            control.setVoidCallable(3);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting void callable",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void openVoidCallCountWithoutMethodCall() {
-        try {
-            control.setVoidCallable();
-            fail("IllegalStateException expected");
-        } catch (Exception expected) {
-            assertEquals(
-                    "method call on the mock needed before setting void callable",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueBoolean() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(false);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueShort() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((short) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueChar() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((char) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueInt() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueLong() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((long) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueFloat() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((float) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueDouble() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue((double) 0);
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void setWrongReturnValueObject() {
-        mock.oneArg(false);
-        try {
-            control.setReturnValue(new Object());
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals("incompatible return value type", expected
-                    .getMessage());
-        }
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class RecordStateInvalidUsageTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void notAMockPassedToExpect() {
+        try {
+            expect(null);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException expected) {
+            assertEquals("no last call on a mock available", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void openVoidCallCountWithoutMethodCall() {
+        try {
+            expectLastCall();
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException expected) {
+            assertEquals("no last call on a mock available", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void setWrongReturnValueBoolean() {
+        try {
+            expect((Object) mock.oneArg(false)).andReturn(false);
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException expected) {
+            assertEquals("incompatible return value type", expected.getMessage());
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/RecordStateMethodCallMissingTest.java b/tests/org/easymock/tests/RecordStateMethodCallMissingTest.java
index 0064776..15e2adf 100644
--- a/tests/org/easymock/tests/RecordStateMethodCallMissingTest.java
+++ b/tests/org/easymock/tests/RecordStateMethodCallMissingTest.java
@@ -1,277 +1,276 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 package org.easymock.tests;
 
 import static org.easymock.EasyMock.*;
 import static org.junit.Assert.*;
 
-import org.easymock.MockControl;
+import org.easymock.IAnswer;
+import org.easymock.internal.MocksControl;
 import org.junit.Before;
 import org.junit.Test;
 
- at SuppressWarnings("deprecation")
+/**
+ * @author OFFIS, Tammo Freese
+ */
 public class RecordStateMethodCallMissingTest {
-    MockControl<IMethods> control;
+
+    private static final String METHOD_CALL_NEEDED = "method call on the mock needed before setting ";
 
     IMethods mock;
 
+    MocksControl control;
+
     @Before
     public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
+        control = (MocksControl) createControl(); // this cast is a hack. It will provoke the errors below but I don't think it can happen using EasyMock normally
+        mock = control.createMock(IMethods.class);
+    }
+
+    private void assertMessage(final String suffix, final IllegalStateException expected) {
+        assertEquals(METHOD_CALL_NEEDED + suffix, expected.getMessage());
     }
 
     @Test
     public void setBooleanReturnValueWithoutMethodCall() {
         try {
-            control.setReturnValue(false);
+            control.andReturn(false);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("return value", expected);
         }
     }
 
     @Test
     public void setLongReturnValueWithoutMethodCall() {
         try {
-            control.setReturnValue(0);
+            control.andReturn(0L);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("return value", expected);
         }
     }
 
     @Test
     public void setFloatReturnValueWithoutMethodCall() {
         try {
-            control.setReturnValue((float) 0.0);
+            control.andReturn(0.0f);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("return value", expected);
         }
     }
 
     @Test
     public void setDoubleReturnValueWithoutMethodCall() {
         try {
-            control.setReturnValue(0.0);
+            control.andReturn(0.0);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("return value", expected);
         }
     }
 
     @Test
     public void setObjectReturnValueWithoutMethodCall() {
         try {
-            control.setReturnValue(null);
+            control.andReturn(null);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void setVoidCallableWithoutMethodCall() {
-        try {
-            control.setVoidCallable();
-            fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting void callable",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("return value", expected);
         }
     }
 
     @Test
     public void setThrowableWithoutMethodCall() {
         try {
-            control.setThrowable(new RuntimeException());
+            control.andThrow(new RuntimeException());
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting Throwable",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("Throwable", expected);
         }
     }
 
     @Test
-    public void setBooleanReturnValueCountWithoutMethodCall() {
+    public void setAnswerWithoutMethodCall() {
         try {
-            control.setReturnValue(false, 3);
+            control.andAnswer(new IAnswer<Object>() {
+                public Object answer() throws Throwable {
+                    return null;
+                }
+
+            });
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("answer", expected);
         }
     }
 
     @Test
-    public void setLongReturnValueCountWithoutMethodCall() {
+    public void setDelegateToWithoutMethodCall() {
         try {
-            control.setReturnValue(0, 3);
+            control.andDelegateTo(null);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("delegate", expected);
         }
     }
 
     @Test
-    public void setFloatReturnValueCountWithoutMethodCall() {
+    public void setAnyTimesWithoutMethodCall() {
         try {
-            control.setReturnValue((float) 0.0, 3);
+            control.anyTimes();
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("times", expected);
         }
     }
 
     @Test
-    public void setDoubleReturnValueCountWithoutMethodCall() {
+    public void setAtLeastOnceWithoutMethodCall() {
         try {
-            control.setReturnValue(0.0, 3);
+            control.atLeastOnce();
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("times", expected);
         }
     }
 
     @Test
-    public void setObjectReturnValueCountWithoutMethodCall() {
+    public void setTimesWithoutMethodCall() {
         try {
-            control.setReturnValue(null, 3);
+            control.times(3);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("times", expected);
         }
     }
 
     @Test
-    public void setVoidCallableCountWithoutMethodCall() {
+    public void setTimesMinMaxWithoutMethodCall() {
         try {
-            control.setVoidCallable(3);
+            control.times(1, 3);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting void callable",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("times", expected);
         }
     }
 
     @Test
-    public void setThrowableCountWithoutMethodCall() {
+    public void setOnceWithoutMethodCall() {
         try {
-            control.setThrowable(new RuntimeException(), 3);
+            control.once();
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting Throwable",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("times", expected);
         }
     }
 
     @Test
     public void setBooleanDefaultReturnValueWithoutMethodCall() {
         try {
-            control.setDefaultReturnValue(false);
+            control.andStubReturn(false);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub return value", expected);
         }
     }
 
     @Test
     public void setLongDefaultReturnValueWithoutMethodCall() {
         try {
-            control.setDefaultReturnValue(0);
+            control.andStubReturn(0L);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub return value", expected);
         }
     }
 
     @Test
     public void setFloatDefaultReturnValueWithoutMethodCall() {
         try {
-            control.setDefaultReturnValue((float) 0.0);
+            control.andStubReturn(0.0f);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub return value", expected);
         }
     }
 
     @Test
     public void setDoubleDefaultReturnValueWithoutMethodCall() {
         try {
-            control.setDefaultReturnValue(0.0);
+            control.andStubReturn(0.0);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub return value", expected);
         }
     }
 
     @Test
     public void setObjectDefaultReturnValueWithoutMethodCall() {
         try {
-            control.setDefaultReturnValue(null);
+            control.andStubReturn(null);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default return value",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub return value", expected);
         }
     }
 
     @Test
     public void setDefaultVoidCallableWithoutMethodCall() {
         try {
-            control.setDefaultVoidCallable();
+            control.asStub();
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default void callable",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub behavior", expected);
         }
     }
 
     @Test
     public void setDefaultThrowableWithoutMethodCall() {
         try {
-            control.setDefaultThrowable(new RuntimeException());
+            control.andStubThrow(new RuntimeException());
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub Throwable", expected);
+        }
+    }
+
+    @Test
+    public void setStubAnswerWithoutMethodCall() {
+        try {
+            control.andStubAnswer(new IAnswer<Object>() {
+                public Object answer() throws Throwable {
+                    return null;
+                }
+
+            });
+            fail("IllegalStateException expected");
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub answer", expected);
+        }
+    }
+
+    @Test
+    public void setStubDelegateToWithoutMethodCall() {
+        try {
+            control.andStubDelegateTo(null);
             fail("IllegalStateException expected");
-        } catch (IllegalStateException expected) {
-            assertEquals(
-                    "method call on the mock needed before setting default Throwable",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertMessage("stub delegate", expected);
         }
     }
 
@@ -281,9 +280,8 @@ public class RecordStateMethodCallMissingTest {
         try {
             expectLastCall().times(3);
             fail();
-        } catch (IllegalStateException expected) {
-            assertEquals("last method called on mock is not a void method",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertEquals("last method called on mock is not a void method", expected.getMessage());
         }
     }
 
@@ -293,9 +291,8 @@ public class RecordStateMethodCallMissingTest {
         try {
             expectLastCall().asStub();
             fail();
-        } catch (IllegalStateException expected) {
-            assertEquals("last method called on mock is not a void method",
-                    expected.getMessage());
+        } catch (final IllegalStateException expected) {
+            assertEquals("last method called on mock is not a void method", expected.getMessage());
         }
     }
 
diff --git a/tests/org/easymock/tests/ReplayStateInvalidCallsTest.java b/tests/org/easymock/tests/ReplayStateInvalidCallsTest.java
index 1f18475..0f13f62 100644
--- a/tests/org/easymock/tests/ReplayStateInvalidCallsTest.java
+++ b/tests/org/easymock/tests/ReplayStateInvalidCallsTest.java
@@ -1,139 +1,152 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import org.easymock.MockControl;
-import org.easymock.internal.MocksBehavior;
-import org.easymock.internal.ReplayState;
-import org.easymock.internal.RuntimeExceptionWrapper;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class ReplayStateInvalidCallsTest {
-
-    private ReplayState control;
-
-    private Exception exception;
-
-    @Before
-    public void setUp() {
-        exception = new Exception();
-        control = new ReplayState(new MocksBehavior(false));
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void expectAndThrowLongWithMinMax() {
-        control.andThrow(exception);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void expectAndReturnObjectWithMinMax() {
-        control.andReturn("");
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void setDefaultMatcher() {
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void asStub() {
-        control.asStub();
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void setMatcher() {
-        control.setMatcher(null, MockControl.ARRAY_MATCHER);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void setDefaultReturnValue() {
-        control.setDefaultReturnValue("");
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void setDefaultThrowable() {
-        control.setDefaultThrowable(exception);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void setDefaultVoidCallable() {
-        control.setDefaultVoidCallable();
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void replay() {
-        control.replay();
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void checkOrder() {
-        control.checkOrder(true);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void makeThreadSafe() {
-        control.makeThreadSafe(true);
-    }
-    
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void andStubReturn() {
-        control.andStubReturn("7");
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void andStubThrow() {
-        control.andStubThrow(new RuntimeException());
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void andStubAnswer() {
-        control.andStubAnswer(null);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void times() {
-        control.times(MockControl.ONE);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void callback() {
-        control.callback(new Runnable() {
-            public void run() {
-            };
-        });
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void andReturn() {
-        control.andReturn(null);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void andThrow() {
-        control.andThrow(new RuntimeException());
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void andAnswer() {
-        control.andAnswer(null);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void defaultThrowable() {
-        control.setDefaultThrowable(new RuntimeException());
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void defaultReturnValue() {
-        control.setDefaultReturnValue(null);
-    }
-
-    @Test(expected = RuntimeExceptionWrapper.class)
-    public void defaultVoidCallable() {
-        control.setDefaultVoidCallable();
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import org.easymock.internal.MocksBehavior;
+import org.easymock.internal.Range;
+import org.easymock.internal.ReplayState;
+import org.easymock.internal.RuntimeExceptionWrapper;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ReplayStateInvalidCallsTest {
+
+    private ReplayState control;
+
+    private Exception exception;
+
+    @Before
+    public void setUp() {
+        exception = new Exception();
+        control = new ReplayState(new MocksBehavior(false));
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void expectAndThrowLongWithMinMax() {
+        control.andThrow(exception);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void expectAndReturnObjectWithMinMax() {
+        control.andReturn("");
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void asStub() {
+        control.asStub();
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void setDefaultReturnValue() {
+        control.setDefaultReturnValue("");
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void setDefaultThrowable() {
+        control.setDefaultThrowable(exception);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void setDefaultVoidCallable() {
+        control.setDefaultVoidCallable();
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void replay() {
+        control.replay();
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void checkOrder() {
+        control.checkOrder(true);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void makeThreadSafe() {
+        control.makeThreadSafe(true);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andStubReturn() {
+        control.andStubReturn("7");
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andStubThrow() {
+        control.andStubThrow(new RuntimeException());
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andStubAnswer() {
+        control.andStubAnswer(null);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andStubDelegateTo() {
+        control.andStubDelegateTo(null);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void times() {
+        control.times(new Range(0, 1));
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void callback() {
+        control.callback(new Runnable() {
+            public void run() {
+            };
+        });
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andReturn() {
+        control.andReturn(null);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andThrow() {
+        control.andThrow(new RuntimeException());
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andAnswer() {
+        control.andAnswer(null);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void andDelegateTo() {
+        control.andDelegateTo(null);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void defaultThrowable() {
+        control.setDefaultThrowable(new RuntimeException());
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void defaultReturnValue() {
+        control.setDefaultReturnValue(null);
+    }
+
+    @Test(expected = RuntimeExceptionWrapper.class)
+    public void defaultVoidCallable() {
+        control.setDefaultVoidCallable();
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/ReplayStateInvalidUsageTest.java b/tests/org/easymock/tests/ReplayStateInvalidUsageTest.java
index 50d20fa..af57082 100644
--- a/tests/org/easymock/tests/ReplayStateInvalidUsageTest.java
+++ b/tests/org/easymock/tests/ReplayStateInvalidUsageTest.java
@@ -1,473 +1,112 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import org.easymock.EasyMock;
-import org.easymock.IExpectationSetters;
-import org.easymock.IMocksControl;
-import org.easymock.MockControl;
-import org.easymock.internal.ReplayState;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class ReplayStateInvalidUsageTest {
-
-    private MockControl<IMethods> control;
-
-    private Exception exception;
-
-    private ReplayState replayState;
-
-    private IMocksControl mocksControl;
-    
-    private IExpectationSetters<String> expectationSetters;
-
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setUp() {
-        exception = new Exception();
-        control = MockControl.createControl(IMethods.class);
-        control.replay();
-        mocksControl = EasyMock.createControl();
-        mocksControl.replay();
-        expectationSetters = (IExpectationSetters<String>) mocksControl; 
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowObjectWithMinMax() {
-        control.expectAndThrow("", exception, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowDoubleWithMinMax() {
-        control.expectAndThrow(0.0d, exception, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowFloatWithMinMax() {
-        control.expectAndThrow(0.0f, exception, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowLongWithMinMax() {
-        control.expectAndThrow(0, exception, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowBooleanWithMinMax() {
-        control.expectAndThrow(false, exception, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowObjectWithCount() {
-        control.expectAndThrow("", exception, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowDoubleWithCount() {
-        control.expectAndThrow(0.0d, exception, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowFloatWithCount() {
-        control.expectAndThrow(0.0f, exception, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowLongWithCount() {
-        control.expectAndThrow(0, exception, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowBooleanWithCount() {
-        control.expectAndThrow(false, exception, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowObjectWithRange() {
-        control.expectAndThrow("", exception, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowDoubleWithRange() {
-        control.expectAndThrow(0.0d, exception, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowFloatWithRange() {
-        control.expectAndThrow(0.0f, exception, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowLongWithRange() {
-        control.expectAndThrow(0, exception, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowBooleanWithRange() {
-        control.expectAndThrow(false, exception, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowObject() {
-        control.expectAndThrow("", exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowDouble() {
-        control.expectAndThrow(0.0d, exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowFloat() {
-        control.expectAndThrow(0.0f, exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowLong() {
-        control.expectAndThrow(0, exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndThrowBoolean() {
-        control.expectAndThrow(false, exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnObjectWithMinMax() {
-        control.expectAndReturn("", "", 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnDoubleWithMinMax() {
-        control.expectAndReturn(0.0d, 0.0d, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnFloatWithMinMax() {
-        control.expectAndReturn(0.0f, 0.0f, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnLongWithMinMax() {
-        control.expectAndReturn(0, 0, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnBooleanWithMinMax() {
-        control.expectAndReturn(false, false, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnObjectWithCount() {
-        control.expectAndReturn("", "", 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnDoubleWithCount() {
-        control.expectAndReturn(0.0d, 0.0d, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnFloatWithCount() {
-        control.expectAndReturn(0.0f, 0.0f, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnLongWithCount() {
-        control.expectAndReturn(0, 0, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnBooleanWithCount() {
-        control.expectAndReturn(false, false, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnObjectWithRange() {
-        control.expectAndReturn("", "", MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnDoubleWithRange() {
-        control.expectAndReturn(0.0d, 0.0d, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnFloatWithRange() {
-        control.expectAndReturn(0.0f, 0.0f, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnLongWithRange() {
-        control.expectAndReturn(0, 0, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnBooleanWithRange() {
-        control.expectAndReturn(false, false, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnObject() {
-        control.expectAndReturn("", "");
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnDouble() {
-        control.expectAndReturn(0.0d, 0.0d);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnFloat() {
-        control.expectAndReturn(0.0f, 0.0f);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnLong() {
-        control.expectAndReturn(0, 0);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void expectAndReturnBoolean() {
-        control.expectAndReturn(false, false);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultMatcher() {
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueObjectWithMinMax() {
-        control.setReturnValue("", 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueDoubleWithMinMax() {
-        control.setReturnValue(0.0d, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueFloatWithMinMax() {
-        control.setReturnValue(0.0f, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueLongWithMinMax() {
-        control.setReturnValue(0, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueBooleanWithMinMax() {
-        control.setReturnValue(false, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setThrowableWithMinMax() {
-        control.setThrowable(exception, 1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setVoidCallableWithMinMax() {
-        control.setVoidCallable(1, 2);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setMatcher() {
-        control.setMatcher(MockControl.ARRAY_MATCHER);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultReturnValueObject() {
-        control.setDefaultReturnValue("");
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultReturnValueDouble() {
-        control.setDefaultReturnValue(0.0d);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultReturnValueFloat() {
-        control.setDefaultReturnValue(0.0f);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultReturnValueLong() {
-        control.setDefaultReturnValue(0);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultReturnValueBoolean() {
-        control.setDefaultReturnValue(false);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultThrowable() {
-        control.setDefaultThrowable(exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setDefaultVoidCallable() {
-        control.setDefaultVoidCallable();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueObjectWithRange() {
-        control.setReturnValue("", MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueLongWithRange() {
-        control.setReturnValue(0, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueFloatWithRange() {
-        control.setReturnValue(0.0f, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueDoubleWithRange() {
-        control.setReturnValue(0.0d, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueBooleanWithRange() {
-        control.setReturnValue(false, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setThrowableWithRange() {
-        control.setThrowable(exception, MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setVoidCallableWithRange() {
-        control.setVoidCallable(MockControl.ONE);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueObjectWithCount() {
-        control.setReturnValue("", 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueLongWithCount() {
-        control.setReturnValue(0, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueFloatWithCount() {
-        control.setReturnValue(0.0f, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueDoubleWithCount() {
-        control.setReturnValue(0.0d, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueBooleanWithCount() {
-        control.setReturnValue(false, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setThrowableWithCount() {
-        control.setThrowable(exception, 1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setVoidCallableWithCount() {
-        control.setVoidCallable(1);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueObject() {
-        control.setReturnValue("");
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueDouble() {
-        control.setReturnValue(0.0d);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueFloat() {
-        control.setReturnValue(0.0f);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueLong() {
-        control.setReturnValue(0);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setReturnValueBoolean() {
-        control.setReturnValue(false);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setThrowable() {
-        control.setThrowable(exception);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void setVoidCallable() {
-        control.setVoidCallable();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void replay() {
-        control.replay();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void createMock() {
-        mocksControl.createMock(IMethods.class);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void createMockWithName() {
-        mocksControl.createMock("", IMethods.class);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void checkOrder() {
-        mocksControl.checkOrder(true);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void makeThreadSafe() {
-        mocksControl.makeThreadSafe(true);
-    }
-    
-    @Test(expected = IllegalStateException.class)
-    public void andStubReturn() {
-        expectationSetters.andStubReturn("7");
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void andStubThrow() {
-        expectationSetters.andStubThrow(new RuntimeException());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void asStub() {
-        expectationSetters.asStub();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void times() {
-        expectationSetters.times(3);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void anyTimes() {
-        expectationSetters.anyTimes();
-    }   
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+
+import org.easymock.EasyMock;
+import org.easymock.IExpectationSetters;
+import org.easymock.IMocksControl;
+import org.easymock.internal.ReplayState;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ReplayStateInvalidUsageTest {
+
+    private IMethods mock;
+
+    private Exception exception;
+
+    private ReplayState replayState;
+
+    private IMocksControl mocksControl;
+
+    private IExpectationSetters<String> expectationSetters;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setUp() {
+        exception = new Exception();
+        mock = EasyMock.createMock(IMethods.class);
+        EasyMock.replay(mock);
+        mocksControl = EasyMock.createControl();
+        mocksControl.replay();
+        expectationSetters = (IExpectationSetters<String>) mocksControl;
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void setVoidCallable() {
+        expectLastCall();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void replay() {
+        EasyMock.replay(mock);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void createMock() {
+        mocksControl.createMock(IMethods.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void createMockWithName() {
+        mocksControl.createMock("", IMethods.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkOrder() {
+        mocksControl.checkOrder(true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void makeThreadSafe() {
+        mocksControl.makeThreadSafe(true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkIsUsedInOneThread() {
+        mocksControl.checkIsUsedInOneThread(true);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void andStubReturn() {
+        expectationSetters.andStubReturn("7");
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void andStubThrow() {
+        expectationSetters.andStubThrow(new RuntimeException());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void asStub() {
+        expectationSetters.asStub();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void times() {
+        expectationSetters.times(3);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void anyTimes() {
+        expectationSetters.anyTimes();
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/ResultTest.java b/tests/org/easymock/tests/ResultTest.java
index f1ff041..cc06d03 100644
--- a/tests/org/easymock/tests/ResultTest.java
+++ b/tests/org/easymock/tests/ResultTest.java
@@ -1,24 +1,59 @@
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.internal.Result;
-import org.junit.Test;
-
-
-public class ResultTest {
-
-    @Test
-    public void createThrowResultToString() {
-        Exception e = new Exception("Error message");
-        Result r = Result.createThrowResult(e);
-        assertEquals("Answer throwing " + e, r.toString());
-    }
-    
-    @Test
-    public void createReturnResultToString() {
-        String value = "My value";
-        Result r = Result.createReturnResult(value);
-        assertEquals("Answer returning " + value, r.toString());
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.junit.Assert.*;
+
+import org.easymock.internal.Result;
+import org.easymock.internal.Results;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ * @author Henri Tremblay
+ */
+public class ResultTest {
+
+    @Test
+    public void createThrowResultToString() {
+        final Exception e = new Exception("Error message");
+        final Result r = Result.createThrowResult(e);
+        assertEquals("Answer throwing " + e, r.toString());
+    }
+
+    @Test
+    public void createReturnResultToString() {
+        final String value = "My value";
+        final Result r = Result.createReturnResult(value);
+        assertEquals("Answer returning " + value, r.toString());
+    }
+
+    @Test
+    public void createDelegateResultToString() {
+        final String value = "my value";
+        final Result r = Result.createDelegatingResult(value);
+        assertEquals("Delegated to " + value, r.toString());
+    }
+
+    @Test
+    public void emptyResults() {
+        // We never create a Results without at least one Range
+        // This test is only to unit test Results with this to cover the case anyway
+        final Results results = new Results();
+        assertFalse(results.hasResults());
+        assertNull(results.next());
+    }
+}
diff --git a/tests/org/easymock/tests/StacktraceTest.java b/tests/org/easymock/tests/StacktraceTest.java
index 867e210..ea12276 100644
--- a/tests/org/easymock/tests/StacktraceTest.java
+++ b/tests/org/easymock/tests/StacktraceTest.java
@@ -1,83 +1,140 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class StacktraceTest {
-
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createStrictControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    private static class ToStringThrowsException {
-        @Override
-        public String toString() {
-            throw new NullPointerException();
-        }
-    }
-
-    @Test
-    public void assertRecordStateNoFillInStacktraceWhenExceptionNotFromEasyMock() {
-        mock.oneArg(new ToStringThrowsException());
-        try {
-            mock.oneArg(new ToStringThrowsException());
-        } catch (NullPointerException expected) {
-            assertTrue("stack trace must not be cut",
-                    Util.getStackTrace(expected).indexOf(
-                            ToStringThrowsException.class.getName()) > 0);
-        }
-    }
-
-    @Test
-    public void assertReplayNoFillInStacktraceWhenExceptionNotFromEasyMock() {
-        mock.oneArg(new ToStringThrowsException());
-        try {
-            control.replay();
-        } catch (NullPointerException expected) {
-            assertTrue("stack trace must not be cut",
-                    Util.getStackTrace(expected).indexOf(
-                            ToStringThrowsException.class.getName()) > 0);
-        }
-    }
-
-    @Test
-    public void assertReplayStateNoFillInStacktraceWhenExceptionNotFromEasyMock() {
-        control.replay();
-        try {
-            mock.oneArg(new ToStringThrowsException());
-        } catch (NullPointerException expected) {
-            assertTrue("stack trace must not be cut",
-                    Util.getStackTrace(expected).indexOf(
-                            ToStringThrowsException.class.getName()) > 0);
-        }
-    }
-
-    @Test
-    public void assertVerifyNoFillInStacktraceWhenExceptionNotFromEasyMock() {
-        mock.oneArg(new ToStringThrowsException());
-        control.setReturnValue("");
-        control.replay();
-        try {
-            control.verify();
-            fail();
-        } catch (NullPointerException expected) {
-            assertTrue("stack trace must not be cut",
-                    Util.getStackTrace(expected).indexOf(
-                            ToStringThrowsException.class.getName()) > 0);
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.easymock.IAnswer;
+import org.easymock.internal.MockInvocationHandler;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class StacktraceTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    private static class ToStringThrowsException {
+        @Override
+        public String toString() {
+            throw new NullPointerException();
+        }
+    }
+
+    @Test
+    public void assertRecordStateNoFillInStacktraceWhenExceptionNotFromEasyMock() {
+        mock.oneArg(new ToStringThrowsException());
+        try {
+            mock.oneArg(new ToStringThrowsException());
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace must not be cut", Util.getStackTrace(expected).indexOf(
+                    ToStringThrowsException.class.getName()) > 0);
+        }
+    }
+
+    @Test
+    public void assertReplayNoFillInStacktraceWhenExceptionNotFromEasyMock() {
+        mock.oneArg(new ToStringThrowsException());
+        try {
+            replay(mock);
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace must not be cut", Util.getStackTrace(expected).indexOf(
+                    ToStringThrowsException.class.getName()) > 0);
+        }
+    }
+
+    @Test
+    public void assertReplayStateNoFillInStacktraceWhenExceptionNotFromEasyMock() {
+        replay(mock);
+        try {
+            mock.oneArg(new ToStringThrowsException());
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace must not be cut", Util.getStackTrace(expected).indexOf(
+                    ToStringThrowsException.class.getName()) > 0);
+        }
+    }
+
+    @Test
+    public void assertVerifyNoFillInStacktraceWhenExceptionNotFromEasyMock() {
+        expect(mock.oneArg(new ToStringThrowsException())).andReturn("");
+        replay(mock);
+        try {
+            verify(mock);
+            fail();
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace must not be cut", Util.getStackTrace(expected).indexOf(
+                    ToStringThrowsException.class.getName()) > 0);
+        }
+    }
+
+    @Test
+    public void assertFillWhenThrowingAnswer() {
+        expect(mock.oneArg("")).andThrow(new NullPointerException());
+        replay(mock);
+        try {
+            mock.oneArg("");
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace should cut", Util.startWithClass(expected, MockInvocationHandler.class));
+        }
+    }
+
+    @Test
+    public void assertNoFillWhenDelegatingAnswer() {
+        final IMethods answer = (IMethods) Proxy.newProxyInstance(getClass().getClassLoader(),
+                new Class<?>[] { IMethods.class }, new InvocationHandler() {
+                    public Object invoke(final Object proxy, final Method method, final Object[] args)
+                            throws Throwable {
+                        throw new NullPointerException();
+                    }
+                });
+        expect(mock.oneArg("")).andDelegateTo(answer);
+        replay(mock);
+        try {
+            mock.oneArg("");
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace must not be cut", Util.startWithClass(expected, Proxy
+                    .getInvocationHandler(answer).getClass()));
+        }
+    }
+
+    @Test
+    public void assertNoFillWhenIAnswerAnswer() {
+        final IAnswer<String> answer = new IAnswer<String>() {
+            public String answer() throws Throwable {
+                throw new NullPointerException();
+            }
+        };
+        expect(mock.oneArg("")).andAnswer(answer);
+        replay(mock);
+        try {
+            mock.oneArg("");
+        } catch (final NullPointerException expected) {
+            assertTrue("stack trace must not be cut", Util.startWithClass(expected, answer.getClass()));
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/UsageCallCountTest.java b/tests/org/easymock/tests/UsageCallCountTest.java
index 61fbbe6..f265063 100644
--- a/tests/org/easymock/tests/UsageCallCountTest.java
+++ b/tests/org/easymock/tests/UsageCallCountTest.java
@@ -1,133 +1,143 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageCallCountTest {
-
-    private MockControl<VoidMethodInterface> control;
-
-    private VoidMethodInterface mock;
-
-    private interface VoidMethodInterface {
-        void method();
-    }
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(VoidMethodInterface.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void mockWithNoExpectedCallsPassesWithNoCalls() {
-        control.replay();
-        control.verify();
-    }
-
-    @Test
-    public void mockWithNoExpectedCallsFailsAtFirstCall() {
-        control.replay();
-        assertMethodCallFails();
-    }
-
-    @Test
-    public void mockWithOneExpectedCallFailsAtVerify() {
-        callMethodOnce();
-        control.replay();
-        assertVerifyFails();
-    }
-
-    @Test
-    public void mockWithOneExpectedCallPassesWithOneCall() {
-        callMethodOnce();
-        control.replay();
-        callMethodOnce();
-        control.verify();
-    }
-
-    @Test
-    public void mockWithOneExpectedCallFailsAtSecondCall() {
-        callMethodOnce();
-        control.replay();
-        callMethodOnce();
-        assertMethodCallFails();
-    }
-
-    @Test
-    public void tooFewCalls() {
-        callMethodThreeTimes();
-        control.replay();
-        callMethodTwice();
-        assertVerifyFails();
-    }
-
-    @Test
-    public void correctNumberOfCalls() {
-        callMethodThreeTimes();
-        control.replay();
-        callMethodThreeTimes();
-        control.verify();
-    }
-
-    @Test
-    public void tooManyCalls() {
-        callMethodThreeTimes();
-        control.replay();
-        callMethodThreeTimes();
-        assertMethodCallFails();
-    }
-
-    private void callMethodOnce() {
-        mock.method();
-    }
-
-    private void callMethodTwice() {
-        mock.method();
-        mock.method();
-    }
-
-    private void callMethodThreeTimes() {
-        mock.method();
-        mock.method();
-        mock.method();
-    }
-
-    private void assertVerifyFails() {
-        try {
-            control.verify();
-            fail("Expected AssertionError");
-        } catch (AssertionError expected) {
-        }
-    }
-
-    private void assertMethodCallFails() {
-        try {
-            mock.method();
-            fail("Expected AssertionError");
-        } catch (AssertionError expected) {
-        }
-    }
-
-    @Test
-    public void noUpperLimitWithoutCallCountSet() {
-        mock.method();
-        control.setVoidCallable(MockControl.ONE_OR_MORE);
-        control.replay();
-        assertVerifyFails();
-        mock.method();
-        control.verify();
-        mock.method();
-        control.verify();
-        mock.method();
-        control.verify();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageCallCountTest {
+
+    private VoidMethodInterface mock;
+
+    private interface VoidMethodInterface {
+        void method();
+    }
+
+    @Before
+    public void setup() {
+        mock = createMock(VoidMethodInterface.class);
+    }
+
+    @Test
+    public void mockWithNoExpectedCallsPassesWithNoCalls() {
+        replay(mock);
+        verify(mock);
+    }
+
+    @Test
+    public void mockWithNoExpectedCallsFailsAtFirstCall() {
+        replay(mock);
+        assertMethodCallFails();
+    }
+
+    @Test
+    public void mockWithOneExpectedCallFailsAtVerify() {
+        callMethodOnce();
+        replay(mock);
+        assertVerifyFails();
+    }
+
+    @Test
+    public void mockWithOneExpectedCallPassesWithOneCall() {
+        callMethodOnce();
+        replay(mock);
+        callMethodOnce();
+        verify(mock);
+    }
+
+    @Test
+    public void mockWithOneExpectedCallFailsAtSecondCall() {
+        callMethodOnce();
+        replay(mock);
+        callMethodOnce();
+        assertMethodCallFails();
+    }
+
+    @Test
+    public void tooFewCalls() {
+        callMethodThreeTimes();
+        replay(mock);
+        callMethodTwice();
+        assertVerifyFails();
+    }
+
+    @Test
+    public void correctNumberOfCalls() {
+        callMethodThreeTimes();
+        replay(mock);
+        callMethodThreeTimes();
+        verify(mock);
+    }
+
+    @Test
+    public void tooManyCalls() {
+        callMethodThreeTimes();
+        replay(mock);
+        callMethodThreeTimes();
+        assertMethodCallFails();
+    }
+
+    private void callMethodOnce() {
+        mock.method();
+    }
+
+    private void callMethodTwice() {
+        mock.method();
+        mock.method();
+    }
+
+    private void callMethodThreeTimes() {
+        mock.method();
+        mock.method();
+        mock.method();
+    }
+
+    private void assertVerifyFails() {
+        try {
+            verify(mock);
+            fail("Expected AssertionError");
+        } catch (final AssertionError expected) {
+        }
+    }
+
+    private void assertMethodCallFails() {
+        try {
+            mock.method();
+            fail("Expected AssertionError");
+        } catch (final AssertionError expected) {
+        }
+    }
+
+    @Test
+    public void noUpperLimitWithoutCallCountSet() {
+        mock.method();
+        expectLastCall().atLeastOnce();
+        replay(mock);
+        assertVerifyFails();
+        mock.method();
+        verify(mock);
+        mock.method();
+        verify(mock);
+        mock.method();
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/UsageDefaultReturnValueTest.java b/tests/org/easymock/tests/UsageDefaultReturnValueTest.java
index e8818a9..3e14f41 100644
--- a/tests/org/easymock/tests/UsageDefaultReturnValueTest.java
+++ b/tests/org/easymock/tests/UsageDefaultReturnValueTest.java
@@ -1,126 +1,130 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageDefaultReturnValueTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void defaultReturnValue() {
-        mock.threeArgumentMethod(7, "", "test");
-        control.setReturnValue("test", 1);
-
-        mock.threeArgumentMethod(8, null, "test2");
-        control.setReturnValue("test2", 1);
-
-        Object defaultValue = new Object();
-        control.setDefaultReturnValue(defaultValue);
-
-        control.replay();
-        assertEquals("test", mock.threeArgumentMethod(7, "", "test"));
-        assertEquals("test2", mock.threeArgumentMethod(8, null, "test2"));
-        assertSame(defaultValue, mock.threeArgumentMethod(7, new Object(),
-                "test"));
-        assertSame(defaultValue, mock.threeArgumentMethod(7, "", "test"));
-        assertSame(defaultValue, mock.threeArgumentMethod(8, null, "test"));
-        assertSame(defaultValue, mock.threeArgumentMethod(9, null, "test"));
-
-        control.verify();
-    }
-
-    @Test
-    public void defaultVoidCallable() {
-
-        mock.twoArgumentMethod(1, 2);
-        control.setDefaultVoidCallable();
-
-        mock.twoArgumentMethod(1, 1);
-        RuntimeException expected = new RuntimeException();
-        control.setThrowable(expected);
-
-        control.replay();
-        mock.twoArgumentMethod(2, 1);
-        mock.twoArgumentMethod(1, 2);
-        mock.twoArgumentMethod(3, 7);
-
-        try {
-            mock.twoArgumentMethod(1, 1);
-            fail("RuntimeException expected");
-        } catch (RuntimeException actual) {
-            assertSame(expected, actual);
-        }
-
-    }
-
-    @Test
-    public void defaultThrowable() {
-        mock.twoArgumentMethod(1, 2);
-        control.setVoidCallable();
-        mock.twoArgumentMethod(1, 1);
-        control.setVoidCallable();
-
-        RuntimeException expected = new RuntimeException();
-        control.setDefaultThrowable(expected);
-
-        control.replay();
-
-        mock.twoArgumentMethod(1, 2);
-        mock.twoArgumentMethod(1, 1);
-        try {
-            mock.twoArgumentMethod(2, 1);
-            fail("RuntimeException expected");
-        } catch (RuntimeException actual) {
-            assertSame(expected, actual);
-        }
-    }
-
-    @Test
-    public void defaultReturnValueBoolean() {
-        mock.booleanReturningMethod(12);
-        control.setReturnValue(true);
-        control.setDefaultReturnValue(false);
-
-        control.replay();
-
-        assertFalse(mock.booleanReturningMethod(11));
-        assertTrue(mock.booleanReturningMethod(12));
-        assertFalse(mock.booleanReturningMethod(13));
-
-        control.verify();
-    }
-
-    @Test
-    public void returnValueAndDefaultReturnValue() throws Exception {
-
-        mock.oneArg("");
-
-        expectLastCall().andReturn("1");
-        control.setDefaultReturnValue("2");
-
-        control.replay();
-
-        assertEquals("1", mock.oneArg(""));
-        assertEquals("2", mock.oneArg(""));
-        assertEquals("2", mock.oneArg("X"));
-
-        control.verify();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageDefaultReturnValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void defaultReturnValue() {
+        expect(mock.threeArgumentMethod(7, "", "test")).andReturn("test");
+
+        expect(mock.threeArgumentMethod(8, null, "test2")).andReturn("test2");
+
+        final Object defaultValue = new Object();
+        expect(mock.threeArgumentMethod(anyInt(), anyObject(), (String) anyObject())).andStubReturn(
+                defaultValue);
+
+        replay(mock);
+        assertEquals("test", mock.threeArgumentMethod(7, "", "test"));
+        assertEquals("test2", mock.threeArgumentMethod(8, null, "test2"));
+        assertSame(defaultValue, mock.threeArgumentMethod(7, new Object(), "test"));
+        assertSame(defaultValue, mock.threeArgumentMethod(7, "", "test"));
+        assertSame(defaultValue, mock.threeArgumentMethod(8, null, "test"));
+        assertSame(defaultValue, mock.threeArgumentMethod(9, null, "test"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void defaultVoidCallable() {
+        mock.twoArgumentMethod(anyInt(), anyInt());
+        expectLastCall().asStub();
+
+        mock.twoArgumentMethod(1, 1);
+        final RuntimeException expected = new RuntimeException();
+        expectLastCall().andThrow(expected);
+
+        replay(mock);
+        mock.twoArgumentMethod(2, 1);
+        mock.twoArgumentMethod(1, 2);
+        mock.twoArgumentMethod(3, 7);
+
+        try {
+            mock.twoArgumentMethod(1, 1);
+            fail("RuntimeException expected");
+        } catch (final RuntimeException actual) {
+            assertSame(expected, actual);
+        }
+    }
+
+    @Test
+    public void defaultThrowable() {
+        mock.twoArgumentMethod(1, 2);
+        expectLastCall();
+        mock.twoArgumentMethod(1, 1);
+        expectLastCall();
+
+        final RuntimeException expected = new RuntimeException();
+        mock.twoArgumentMethod(anyInt(), anyInt());
+        expectLastCall().andStubThrow(expected);
+
+        replay(mock);
+
+        mock.twoArgumentMethod(1, 2);
+        mock.twoArgumentMethod(1, 1);
+        try {
+            mock.twoArgumentMethod(2, 1);
+            fail("RuntimeException expected");
+        } catch (final RuntimeException actual) {
+            assertSame(expected, actual);
+        }
+    }
+
+    @Test
+    public void defaultReturnValueBoolean() {
+        expect(mock.booleanReturningMethod(12)).andReturn(true);
+        expect(mock.booleanReturningMethod(anyInt())).andStubReturn(false);
+
+        replay(mock);
+
+        assertFalse(mock.booleanReturningMethod(11));
+        assertTrue(mock.booleanReturningMethod(12));
+        assertFalse(mock.booleanReturningMethod(13));
+
+        verify(mock);
+    }
+
+    @Test
+    public void returnValueAndDefaultReturnValue() throws Exception {
+
+        expect(mock.oneArg("")).andReturn("1");
+        expect(mock.oneArg((String) anyObject())).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(""));
+        assertEquals("2", mock.oneArg(""));
+        assertEquals("2", mock.oneArg("X"));
+
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/UsageExpectAndDefaultReturnTest.java b/tests/org/easymock/tests/UsageExpectAndDefaultReturnTest.java
index 7caf015..1382a46 100644
--- a/tests/org/easymock/tests/UsageExpectAndDefaultReturnTest.java
+++ b/tests/org/easymock/tests/UsageExpectAndDefaultReturnTest.java
@@ -1,76 +1,84 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Same as UsageExpectAndReturnTest except that each mocked method is called
- * twice to make sure the defaulting works fine.
- * 
- * @author Henri Tremblay
- */
- at SuppressWarnings("deprecation")
-public class UsageExpectAndDefaultReturnTest {
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void booleanType() {
-        control.expectAndDefaultReturn(mock.booleanReturningMethod(4), true);
-        control.replay();
-        assertEquals(true, mock.booleanReturningMethod(4));
-        assertEquals(true, mock.booleanReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void longType() {
-        control.expectAndDefaultReturn(mock.longReturningMethod(4), 12l);
-        control.replay();
-        assertEquals(12l, mock.longReturningMethod(4));
-        assertEquals(12l, mock.longReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void floatType() {
-        control.expectAndDefaultReturn(mock.floatReturningMethod(4), 12f);
-        control.replay();
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        control.verify();
-    }
-
-    @Test
-    public void doubleType() {
-        control.expectAndDefaultReturn(mock.doubleReturningMethod(4), 12.0);
-        control.replay();
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        control.verify();
-    }
-
-    @Test
-    public void objectType() {
-        control.expectAndDefaultReturn(mock.objectReturningMethod(4), "12");
-        control.replay();
-        assertEquals("12", mock.objectReturningMethod(4));
-        assertEquals("12", mock.objectReturningMethod(4));
-        control.verify();
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Same as UsageExpectAndReturnTest except that each mocked method is called
+ * twice to make sure the defaulting works fine.
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageExpectAndDefaultReturnTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void booleanType() {
+        expect(mock.booleanReturningMethod(4)).andStubReturn(true);
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(4));
+        assertEquals(true, mock.booleanReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void longType() {
+        expect(mock.longReturningMethod(4)).andStubReturn(12l);
+        replay(mock);
+        assertEquals(12l, mock.longReturningMethod(4));
+        assertEquals(12l, mock.longReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void floatType() {
+        expect(mock.floatReturningMethod(4)).andStubReturn(12f);
+        replay(mock);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        verify(mock);
+    }
+
+    @Test
+    public void doubleType() {
+        expect(mock.doubleReturningMethod(4)).andStubReturn(12.0);
+        replay(mock);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        verify(mock);
+    }
+
+    @Test
+    public void objectType() {
+        expect(mock.objectReturningMethod(4)).andStubReturn("12");
+        replay(mock);
+        assertEquals("12", mock.objectReturningMethod(4));
+        assertEquals("12", mock.objectReturningMethod(4));
+        verify(mock);
+    }
+
+}
diff --git a/tests/org/easymock/tests/UsageExpectAndDefaultThrowTest.java b/tests/org/easymock/tests/UsageExpectAndDefaultThrowTest.java
index 5a86915..70e376f 100644
--- a/tests/org/easymock/tests/UsageExpectAndDefaultThrowTest.java
+++ b/tests/org/easymock/tests/UsageExpectAndDefaultThrowTest.java
@@ -1,156 +1,159 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Same as UsageExpectAndThrowTest except that each mocked method is called
- * twice to make sure the defaulting works fine.
- * 
- * @author Henri Tremblay
- */
- at SuppressWarnings("deprecation")
-public class UsageExpectAndDefaultThrowTest {
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    private static RuntimeException EXCEPTION = new RuntimeException();
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void booleanType() {
-        control
-                .expectAndDefaultThrow(mock.booleanReturningMethod(4),
-                        EXCEPTION);
-        control.replay();
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void longType() {
-        control.expectAndDefaultThrow(mock.longReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void floatType() {
-        control.expectAndDefaultThrow(mock.floatReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void doubleType() {
-        control.expectAndDefaultThrow(mock.doubleReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void object() {
-        control.expectAndDefaultThrow(mock.objectReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void throwableAndDefaultThrowable() throws Exception {
-
-        mock.oneArg("1");
-
-        expectLastCall().andThrow(new IllegalArgumentException());
-        control.setDefaultThrowable(new IllegalStateException());
-
-        control.replay();
-
-        try {
-            mock.oneArg("1");
-        } catch (IllegalArgumentException ignored) {
-        }
-        try {
-            mock.oneArg("1");
-        } catch (IllegalStateException ignored) {
-        }
-        try {
-            mock.oneArg("2");
-        } catch (IllegalStateException ignored) {
-        }
-        control.verify();
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Same as UsageExpectAndThrowTest except that each mocked method is called
+ * twice to make sure the defaulting works fine.
+ * 
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageExpectAndDefaultThrowTest {
+
+    private IMethods mock;
+
+    private static RuntimeException EXCEPTION = new RuntimeException();
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void booleanType() {
+        expect(mock.booleanReturningMethod(4)).andStubThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void longType() {
+        expect(mock.longReturningMethod(4)).andStubThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void floatType() {
+        expect(mock.floatReturningMethod(4)).andStubThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void doubleType() {
+        expect(mock.doubleReturningMethod(4)).andStubThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void object() {
+        expect(mock.objectReturningMethod(4)).andStubThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void throwableAndDefaultThrowable() throws Exception {
+
+        expect(mock.oneArg("1")).andThrow(new IllegalArgumentException());
+        expect(mock.oneArg((String) anyObject())).andStubThrow(new IllegalStateException());
+
+        replay(mock);
+
+        try {
+            mock.oneArg("1");
+        } catch (final IllegalArgumentException ignored) {
+        }
+        try {
+            mock.oneArg("1");
+        } catch (final IllegalStateException ignored) {
+        }
+        try {
+            mock.oneArg("2");
+        } catch (final IllegalStateException ignored) {
+        }
+        verify(mock);
+    }
+
+}
diff --git a/tests/org/easymock/tests/UsageExpectAndReturnTest.java b/tests/org/easymock/tests/UsageExpectAndReturnTest.java
index b48c41c..08236bc 100644
--- a/tests/org/easymock/tests/UsageExpectAndReturnTest.java
+++ b/tests/org/easymock/tests/UsageExpectAndReturnTest.java
@@ -1,199 +1,205 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageExpectAndReturnTest {
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void booleanType() {
-        control.expectAndReturn(mock.booleanReturningMethod(4), true);
-        control.replay();
-        assertEquals(true, mock.booleanReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void longType() {
-        control.expectAndReturn(mock.longReturningMethod(4), 12l);
-        control.replay();
-        assertEquals((long) 12, mock.longReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void floatType() {
-        control.expectAndReturn(mock.floatReturningMethod(4), 12f);
-        control.replay();
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        control.verify();
-    }
-
-    @Test
-    public void doubleType() {
-        control.expectAndReturn(mock.doubleReturningMethod(4), 12.0);
-        control.replay();
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        control.verify();
-    }
-
-    @Test
-    public void object() {
-        control.expectAndReturn(mock.objectReturningMethod(4), "12");
-        control.replay();
-        assertEquals("12", mock.objectReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void booleanAndRange() {
-        control.expectAndReturn(mock.booleanReturningMethod(4), true,
-                MockControl.ONE);
-        control.replay();
-        assertEquals(true, mock.booleanReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void longAndRange() {
-        control.expectAndReturn(mock.longReturningMethod(4), 12l,
-                MockControl.ONE);
-        control.replay();
-        assertEquals((long) 12, mock.longReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void floatAndRange() {
-        control.expectAndReturn(mock.floatReturningMethod(4), 12f,
-                MockControl.ONE);
-        control.replay();
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        control.verify();
-    }
-
-    @Test
-    public void doubleAndRange() {
-        control.expectAndReturn(mock.doubleReturningMethod(4), 12.0,
-                MockControl.ONE);
-        control.replay();
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        control.verify();
-    }
-
-    @Test
-    public void objectAndRange() {
-        control.expectAndReturn(mock.objectReturningMethod(4), "12",
-                MockControl.ONE);
-        control.replay();
-        assertEquals("12", mock.objectReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void booleanAndCount() {
-        control.expectAndReturn(mock.booleanReturningMethod(4), true, 2);
-        control.replay();
-        assertEquals(true, mock.booleanReturningMethod(4));
-        assertEquals(true, mock.booleanReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void longAndCount() {
-        control.expectAndReturn(mock.longReturningMethod(4), 12l, 2);
-        control.replay();
-        assertEquals((long) 12, mock.longReturningMethod(4));
-        assertEquals((long) 12, mock.longReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void floatAndCount() {
-        control.expectAndReturn(mock.floatReturningMethod(4), 12f, 2);
-        control.replay();
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        control.verify();
-    }
-
-    @Test
-    public void doubleAndCount() {
-        control.expectAndReturn(mock.doubleReturningMethod(4), 12.0, 2);
-        control.replay();
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        control.verify();
-    }
-
-    @Test
-    public void objectAndCount() {
-        control.expectAndReturn(mock.objectReturningMethod(4), "12", 2);
-        control.replay();
-        assertEquals("12", mock.objectReturningMethod(4));
-        assertEquals("12", mock.objectReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void booleanAndMinMax() {
-        control.expectAndReturn(mock.booleanReturningMethod(4), true, 2, 3);
-        control.replay();
-        assertEquals(true, mock.booleanReturningMethod(4));
-        assertEquals(true, mock.booleanReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void longAndMinMax() {
-        control.expectAndReturn(mock.longReturningMethod(4), 12l, 2, 3);
-        control.replay();
-        assertEquals((long) 12, mock.longReturningMethod(4));
-        assertEquals((long) 12, mock.longReturningMethod(4));
-        control.verify();
-    }
-
-    @Test
-    public void floatAndMinMax() {
-        control.expectAndReturn(mock.floatReturningMethod(4), 12f, 2, 3);
-        control.replay();
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        assertEquals(12f, mock.floatReturningMethod(4), 0f);
-        control.verify();
-    }
-
-    @Test
-    public void doubleAndMinMax() {
-        control.expectAndReturn(mock.doubleReturningMethod(4), 12.0, 2, 3);
-        control.replay();
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
-        control.verify();
-    }
-
-    @Test
-    public void objectAndMinMax() {
-        control.expectAndReturn(mock.objectReturningMethod(4), "12", 2, 3);
-        control.replay();
-        assertEquals("12", mock.objectReturningMethod(4));
-        assertEquals("12", mock.objectReturningMethod(4));
-        control.verify();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageExpectAndReturnTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void booleanType() {
+        expect(mock.booleanReturningMethod(4)).andReturn(true);
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void longType() {
+        expect(mock.longReturningMethod(4)).andReturn(12l);
+        replay(mock);
+        assertEquals(12, mock.longReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void floatType() {
+        expect(mock.floatReturningMethod(4)).andReturn(12f);
+        replay(mock);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        verify(mock);
+    }
+
+    @Test
+    public void doubleType() {
+        expect(mock.doubleReturningMethod(4)).andReturn(12.0);
+        replay(mock);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        verify(mock);
+    }
+
+    @Test
+    public void object() {
+        expect(mock.objectReturningMethod(4)).andReturn("12");
+        replay(mock);
+        assertEquals("12", mock.objectReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void booleanAndRange() {
+        expect(mock.booleanReturningMethod(4)).andReturn(true).once();
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void longAndRange() {
+        expect(mock.longReturningMethod(4)).andReturn(12l).once();
+        replay(mock);
+        assertEquals(12, mock.longReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void floatAndRange() {
+        expect(mock.floatReturningMethod(4)).andReturn(12f).once();
+        replay(mock);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        verify(mock);
+    }
+
+    @Test
+    public void doubleAndRange() {
+        expect(mock.doubleReturningMethod(4)).andReturn(12.0).once();
+        replay(mock);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        verify(mock);
+    }
+
+    @Test
+    public void objectAndRange() {
+        expect(mock.objectReturningMethod(4)).andReturn("12").once();
+        replay(mock);
+        assertEquals("12", mock.objectReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void booleanAndCount() {
+        expect(mock.booleanReturningMethod(4)).andReturn(true).times(2);
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(4));
+        assertEquals(true, mock.booleanReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void longAndCount() {
+        expect(mock.longReturningMethod(4)).andReturn(12l).times(2);
+        replay(mock);
+        assertEquals(12, mock.longReturningMethod(4));
+        assertEquals(12, mock.longReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void floatAndCount() {
+        expect(mock.floatReturningMethod(4)).andReturn(12f).times(2);
+        replay(mock);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        verify(mock);
+    }
+
+    @Test
+    public void doubleAndCount() {
+        expect(mock.doubleReturningMethod(4)).andReturn(12.0).times(2);
+        replay(mock);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        verify(mock);
+    }
+
+    @Test
+    public void objectAndCount() {
+        expect(mock.objectReturningMethod(4)).andReturn("12").times(2);
+        replay(mock);
+        assertEquals("12", mock.objectReturningMethod(4));
+        assertEquals("12", mock.objectReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void booleanAndMinMax() {
+        expect(mock.booleanReturningMethod(4)).andReturn(true).times(2, 3);
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(4));
+        assertEquals(true, mock.booleanReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void longAndMinMax() {
+        expect(mock.longReturningMethod(4)).andReturn(12l).times(2, 3);
+        replay(mock);
+        assertEquals(12, mock.longReturningMethod(4));
+        assertEquals(12, mock.longReturningMethod(4));
+        verify(mock);
+    }
+
+    @Test
+    public void floatAndMinMax() {
+        expect(mock.floatReturningMethod(4)).andReturn(12f).times(2, 3);
+        replay(mock);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        assertEquals(12f, mock.floatReturningMethod(4), 0f);
+        verify(mock);
+    }
+
+    @Test
+    public void doubleAndMinMax() {
+        expect(mock.doubleReturningMethod(4)).andReturn(12.0).times(2, 3);
+        replay(mock);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        assertEquals(12.0, mock.doubleReturningMethod(4), 0.0);
+        verify(mock);
+    }
+
+    @Test
+    public void objectAndMinMax() {
+        expect(mock.objectReturningMethod(4)).andReturn("12").times(2, 3);
+        replay(mock);
+        assertEquals("12", mock.objectReturningMethod(4));
+        assertEquals("12", mock.objectReturningMethod(4));
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/UsageExpectAndThrowTest.java b/tests/org/easymock/tests/UsageExpectAndThrowTest.java
index d5d9125..891b010 100644
--- a/tests/org/easymock/tests/UsageExpectAndThrowTest.java
+++ b/tests/org/easymock/tests/UsageExpectAndThrowTest.java
@@ -1,387 +1,393 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageExpectAndThrowTest {
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    private static RuntimeException EXCEPTION = new RuntimeException();
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void booleanType() {
-        control.expectAndThrow(mock.booleanReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void longType() {
-        control.expectAndThrow(mock.longReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void floatType() {
-        control.expectAndThrow(mock.floatReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void doubleType() {
-        control.expectAndThrow(mock.doubleReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void object() {
-        control.expectAndThrow(mock.objectReturningMethod(4), EXCEPTION);
-        control.replay();
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void booleanAndRange() {
-        control.expectAndThrow(mock.booleanReturningMethod(4), EXCEPTION,
-                MockControl.ONE);
-        control.replay();
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void longAndRange() {
-        control.expectAndThrow(mock.longReturningMethod(4), EXCEPTION,
-                MockControl.ONE);
-        control.replay();
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void floatAndRange() {
-        control.expectAndThrow(mock.floatReturningMethod(4), EXCEPTION,
-                MockControl.ONE);
-        control.replay();
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void doubleAndRange() {
-        control.expectAndThrow(mock.doubleReturningMethod(4), EXCEPTION,
-                MockControl.ONE);
-        control.replay();
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void objectAndRange() {
-        control.expectAndThrow(mock.objectReturningMethod(4), EXCEPTION,
-                MockControl.ONE);
-        control.replay();
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void booleanAndCount() {
-        control.expectAndThrow(mock.booleanReturningMethod(4), EXCEPTION, 2);
-        control.replay();
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void longAndCount() {
-        control.expectAndThrow(mock.longReturningMethod(4), EXCEPTION, 2);
-        control.replay();
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void floatAndCount() {
-        control.expectAndThrow(mock.floatReturningMethod(4), EXCEPTION, 2);
-        control.replay();
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void doubleAndCount() {
-        control.expectAndThrow(mock.doubleReturningMethod(4), EXCEPTION, 2);
-        control.replay();
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void objectAndCount() {
-        control.expectAndThrow(mock.objectReturningMethod(4), EXCEPTION, 2);
-        control.replay();
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void booleanAndMinMax() {
-        control.expectAndThrow(mock.booleanReturningMethod(4), EXCEPTION, 2, 3);
-        control.replay();
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-        try {
-            mock.booleanReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void longAndMinMax() {
-        control.expectAndThrow(mock.longReturningMethod(4), EXCEPTION, 2, 3);
-        control.replay();
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-        try {
-            mock.longReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void floatAndMinMax() {
-        control.expectAndThrow(mock.floatReturningMethod(4), EXCEPTION, 2, 3);
-        control.replay();
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-        try {
-            mock.floatReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void doubleAndMinMax() {
-        control.expectAndThrow(mock.doubleReturningMethod(4), EXCEPTION, 2, 3);
-        control.replay();
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-        try {
-            mock.doubleReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-    @Test
-    public void objectAndMinMax() {
-        control.expectAndThrow(mock.objectReturningMethod(4), EXCEPTION, 2, 3);
-        control.replay();
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-        try {
-            mock.objectReturningMethod(4);
-            fail();
-        } catch (RuntimeException exception) {
-            assertSame(EXCEPTION, exception);
-        }
-        control.verify();
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageExpectAndThrowTest {
+
+    private IMethods mock;
+
+    private static RuntimeException EXCEPTION = new RuntimeException();
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void booleanType() {
+        expect(mock.booleanReturningMethod(4)).andThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void longType() {
+        expect(mock.longReturningMethod(4)).andThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void floatType() {
+        expect(mock.floatReturningMethod(4)).andThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void doubleType() {
+        expect(mock.doubleReturningMethod(4)).andThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void object() {
+        expect(mock.objectReturningMethod(4)).andThrow(EXCEPTION);
+        replay(mock);
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void booleanAndRange() {
+        expect(mock.booleanReturningMethod(4)).andThrow(EXCEPTION).once();
+        replay(mock);
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void longAndRange() {
+        expect(mock.longReturningMethod(4)).andThrow(EXCEPTION).once();
+        replay(mock);
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void floatAndRange() {
+        expect(mock.floatReturningMethod(4)).andThrow(EXCEPTION).once();
+        replay(mock);
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void doubleAndRange() {
+        expect(mock.doubleReturningMethod(4)).andThrow(EXCEPTION).once();
+        replay(mock);
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void objectAndRange() {
+        expect(mock.objectReturningMethod(4)).andThrow(EXCEPTION).once();
+        replay(mock);
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void booleanAndCount() {
+        expect(mock.booleanReturningMethod(4)).andThrow(EXCEPTION).times(2);
+        replay(mock);
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void longAndCount() {
+        expect(mock.longReturningMethod(4)).andThrow(EXCEPTION).times(2);
+        replay(mock);
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void floatAndCount() {
+        expect(mock.floatReturningMethod(4)).andThrow(EXCEPTION).times(2);
+        replay(mock);
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void doubleAndCount() {
+        expect(mock.doubleReturningMethod(4)).andThrow(EXCEPTION).times(2);
+        replay(mock);
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void objectAndCount() {
+        expect(mock.objectReturningMethod(4)).andThrow(EXCEPTION).times(2);
+        replay(mock);
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void booleanAndMinMax() {
+        expect(mock.booleanReturningMethod(4)).andThrow(EXCEPTION).times(2, 3);
+        replay(mock);
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+        try {
+            mock.booleanReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void longAndMinMax() {
+        expect(mock.longReturningMethod(4)).andThrow(EXCEPTION).times(2, 3);
+        replay(mock);
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+        try {
+            mock.longReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void floatAndMinMax() {
+        expect(mock.floatReturningMethod(4)).andThrow(EXCEPTION).times(2, 3);
+        replay(mock);
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+        try {
+            mock.floatReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void doubleAndMinMax() {
+        expect(mock.doubleReturningMethod(4)).andThrow(EXCEPTION).times(2, 3);
+        replay(mock);
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+        try {
+            mock.doubleReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+    @Test
+    public void objectAndMinMax() {
+        expect(mock.objectReturningMethod(4)).andThrow(EXCEPTION).times(2, 3);
+        replay(mock);
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+        try {
+            mock.objectReturningMethod(4);
+            fail();
+        } catch (final RuntimeException exception) {
+            assertSame(EXCEPTION, exception);
+        }
+        verify(mock);
+    }
+
+}
diff --git a/tests/org/easymock/tests/UsageFloatingPointReturnValueTest.java b/tests/org/easymock/tests/UsageFloatingPointReturnValueTest.java
index d4faed5..6204362 100644
--- a/tests/org/easymock/tests/UsageFloatingPointReturnValueTest.java
+++ b/tests/org/easymock/tests/UsageFloatingPointReturnValueTest.java
@@ -1,54 +1,63 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageFloatingPointReturnValueTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void returnFloat() {
-        mock.floatReturningMethod(0);
-        control.setReturnValue(25.0F);
-        control.setDefaultReturnValue(34.0F);
-
-        control.replay();
-
-        assertEquals(25.0F, mock.floatReturningMethod(0), 0.0F);
-        assertEquals(34.0F, mock.floatReturningMethod(-4), 0.0F);
-        assertEquals(34.0F, mock.floatReturningMethod(12), 0.0F);
-
-        control.verify();
-    }
-
-    @Test
-    public void returnDouble() {
-        mock.doubleReturningMethod(0);
-        control.setReturnValue(25.0);
-        control.setDefaultReturnValue(34.0);
-
-        control.replay();
-
-        assertEquals(25.0, mock.doubleReturningMethod(0), 0.0);
-        assertEquals(34.0, mock.doubleReturningMethod(-4), 0.0);
-        assertEquals(34.0, mock.doubleReturningMethod(12), 0.0);
-
-        control.verify();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageFloatingPointReturnValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void returnFloat() {
+        expect(mock.floatReturningMethod(0)).andReturn(25.0F);
+        expect(mock.floatReturningMethod(anyInt())).andStubReturn(34.0F);
+
+        replay(mock);
+
+        assertEquals(25.0F, mock.floatReturningMethod(0), 0.0F);
+        assertEquals(34.0F, mock.floatReturningMethod(-4), 0.0F);
+        assertEquals(34.0F, mock.floatReturningMethod(12), 0.0F);
+
+        verify(mock);
+    }
+
+    @Test
+    public void returnDouble() {
+        expect(mock.doubleReturningMethod(0)).andReturn(25.0);
+        expect(mock.doubleReturningMethod(anyInt())).andStubReturn(34.0);
+
+        replay(mock);
+
+        assertEquals(25.0, mock.doubleReturningMethod(0), 0.0);
+        assertEquals(34.0, mock.doubleReturningMethod(-4), 0.0);
+        assertEquals(34.0, mock.doubleReturningMethod(12), 0.0);
+
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/UsageLongCompatibleReturnValueTest.java b/tests/org/easymock/tests/UsageLongCompatibleReturnValueTest.java
index 3f43802..0e1fc19 100644
--- a/tests/org/easymock/tests/UsageLongCompatibleReturnValueTest.java
+++ b/tests/org/easymock/tests/UsageLongCompatibleReturnValueTest.java
@@ -1,99 +1,105 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageLongCompatibleReturnValueTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void returnByte() {
-        mock.byteReturningMethod(0);
-        control.setReturnValue(25);
-        control.setDefaultReturnValue(34);
-
-        control.replay();
-
-        assertEquals((byte) 25, mock.byteReturningMethod(0));
-        assertEquals((byte) 34, mock.byteReturningMethod(-4));
-        assertEquals((byte) 34, mock.byteReturningMethod(12));
-
-        control.verify();
-    }
-
-    @Test
-    public void returnShort() {
-        mock.shortReturningMethod(0);
-        control.setReturnValue(25);
-        control.setDefaultReturnValue(34);
-
-        control.replay();
-
-        assertEquals((short) 25, mock.shortReturningMethod(0));
-        assertEquals((short) 34, mock.shortReturningMethod(-4));
-        assertEquals((short) 34, mock.shortReturningMethod(12));
-
-        control.verify();
-    }
-
-    @Test
-    public void returnChar() {
-        mock.charReturningMethod(0);
-        control.setReturnValue(25);
-        control.setDefaultReturnValue(34);
-
-        control.replay();
-
-        assertEquals((char) 25, mock.charReturningMethod(0));
-        assertEquals((char) 34, mock.charReturningMethod(-4));
-        assertEquals((char) 34, mock.charReturningMethod(12));
-
-        control.verify();
-    }
-
-    @Test
-    public void returnInt() {
-        mock.intReturningMethod(0);
-        control.setReturnValue(25);
-        control.setDefaultReturnValue(34);
-
-        control.replay();
-
-        assertEquals(25, mock.intReturningMethod(0));
-        assertEquals(34, mock.intReturningMethod(-4));
-        assertEquals(34, mock.intReturningMethod(12));
-
-        control.verify();
-    }
-
-    @Test
-    public void returnLong() {
-        mock.longReturningMethod(0);
-        control.setReturnValue(25);
-        control.setDefaultReturnValue(34);
-
-        control.replay();
-
-        assertEquals((long) 25, mock.longReturningMethod(0));
-        assertEquals((long) 34, mock.longReturningMethod(-4));
-        assertEquals((long) 34, mock.longReturningMethod(12));
-
-        control.verify();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageLongCompatibleReturnValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void returnByte() {
+        expect(mock.byteReturningMethod(0)).andReturn((byte) 25);
+        expect(mock.byteReturningMethod(anyInt())).andStubReturn((byte) 34);
+
+        replay(mock);
+
+        assertEquals((byte) 25, mock.byteReturningMethod(0));
+        assertEquals((byte) 34, mock.byteReturningMethod(-4));
+        assertEquals((byte) 34, mock.byteReturningMethod(12));
+
+        verify(mock);
+    }
+
+    @Test
+    public void returnShort() {
+        expect(mock.shortReturningMethod(0)).andReturn((short) 25);
+        expect(mock.shortReturningMethod(anyInt())).andStubReturn((short) 34);
+
+        replay(mock);
+
+        assertEquals((short) 25, mock.shortReturningMethod(0));
+        assertEquals((short) 34, mock.shortReturningMethod(-4));
+        assertEquals((short) 34, mock.shortReturningMethod(12));
+
+        verify(mock);
+    }
+
+    @Test
+    public void returnChar() {
+        expect(mock.charReturningMethod(0)).andReturn((char) 25);
+        expect(mock.charReturningMethod(anyInt())).andStubReturn((char) 34);
+
+        replay(mock);
+
+        assertEquals((char) 25, mock.charReturningMethod(0));
+        assertEquals((char) 34, mock.charReturningMethod(-4));
+        assertEquals((char) 34, mock.charReturningMethod(12));
+
+        verify(mock);
+    }
+
+    @Test
+    public void returnInt() {
+        expect(mock.intReturningMethod(0)).andReturn(25);
+        expect(mock.intReturningMethod(anyInt())).andStubReturn(34);
+
+        replay(mock);
+
+        assertEquals(25, mock.intReturningMethod(0));
+        assertEquals(34, mock.intReturningMethod(-4));
+        assertEquals(34, mock.intReturningMethod(12));
+
+        verify(mock);
+    }
+
+    @Test
+    public void returnLong() {
+        expect(mock.longReturningMethod(0)).andReturn(25L);
+        expect(mock.longReturningMethod(anyInt())).andStubReturn(34L);
+
+        replay(mock);
+
+        assertEquals(25, mock.longReturningMethod(0));
+        assertEquals(34, mock.longReturningMethod(-4));
+        assertEquals(34, mock.longReturningMethod(12));
+
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests/UsageOverloadedDefaultValueTest.java b/tests/org/easymock/tests/UsageOverloadedDefaultValueTest.java
index aeb3e95..47b65a3 100644
--- a/tests/org/easymock/tests/UsageOverloadedDefaultValueTest.java
+++ b/tests/org/easymock/tests/UsageOverloadedDefaultValueTest.java
@@ -1,112 +1,113 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageOverloadedDefaultValueTest {
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void overloading() {
-
-        mock.oneArg(true);
-        control.setReturnValue("true");
-        control.setDefaultReturnValue("false");
-
-        mock.oneArg((byte) 0);
-        control.setReturnValue("byte 0");
-        control.setDefaultReturnValue("byte 1");
-
-        mock.oneArg((short) 0);
-        control.setReturnValue("short 0");
-        control.setDefaultReturnValue("short 1");
-
-        mock.oneArg((char) 0);
-        control.setReturnValue("char 0");
-        control.setDefaultReturnValue("char 1");
-
-        mock.oneArg(0);
-        control.setReturnValue("int 0");
-        control.setDefaultReturnValue("int 1");
-
-        mock.oneArg((long) 0);
-        control.setReturnValue("long 0");
-        control.setDefaultReturnValue("long 1");
-
-        mock.oneArg((float) 0);
-        control.setReturnValue("float 0");
-        control.setDefaultReturnValue("float 1");
-
-        mock.oneArg(0.0);
-        control.setReturnValue("double 0");
-        control.setDefaultReturnValue("double 1");
-
-        mock.oneArg("Object 0");
-        control.setReturnValue("String 0");
-        control.setDefaultReturnValue("String 1");
-
-        control.replay();
-
-        assertEquals("true", mock.oneArg(true));
-        assertEquals("false", mock.oneArg(false));
-
-        assertEquals("byte 0", mock.oneArg((byte) 0));
-        assertEquals("byte 1", mock.oneArg((byte) 1));
-
-        assertEquals("short 0", mock.oneArg((short) 0));
-        assertEquals("short 1", mock.oneArg((short) 1));
-
-        assertEquals("char 0", mock.oneArg((char) 0));
-        assertEquals("char 1", mock.oneArg((char) 1));
-
-        assertEquals("int 0", mock.oneArg(0));
-        assertEquals("int 1", mock.oneArg(1));
-
-        assertEquals("long 0", mock.oneArg((long) 0));
-        assertEquals("long 1", mock.oneArg((long) 1));
-
-        assertEquals("float 0", mock.oneArg((float) 0.0));
-        assertEquals("float 1", mock.oneArg((float) 1.0));
-
-        assertEquals("double 0", mock.oneArg(0.0));
-        assertEquals("double 1", mock.oneArg(1.0));
-
-        assertEquals("String 0", mock.oneArg("Object 0"));
-        assertEquals("String 1", mock.oneArg("Object 1"));
-
-        control.verify();
-    }
-
-    @Test
-    public void defaultThrowable() {
-
-        mock.oneArg("Object");
-        RuntimeException expected = new RuntimeException();
-        control.setDefaultThrowable(expected);
-
-        control.replay();
-
-        try {
-            mock.oneArg("Something else");
-            fail("runtime exception expected");
-        } catch (RuntimeException expectedException) {
-            assertSame(expected, expectedException);
-        }
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageOverloadedDefaultValueTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void overloading() {
+
+        expect(mock.oneArg(true)).andReturn("true");
+        expect(mock.oneArg(anyBoolean())).andStubReturn("false");
+
+        expect(mock.oneArg((byte) 0)).andReturn("byte 0");
+        expect(mock.oneArg(anyByte())).andStubReturn("byte 1");
+
+        expect(mock.oneArg((short) 0)).andReturn("short 0");
+        expect(mock.oneArg(anyShort())).andStubReturn("short 1");
+
+        expect(mock.oneArg((char) 0)).andReturn("char 0");
+        expect(mock.oneArg(anyChar())).andStubReturn("char 1");
+
+        expect(mock.oneArg(0)).andReturn("int 0");
+        expect(mock.oneArg(anyInt())).andStubReturn("int 1");
+
+        expect(mock.oneArg(0L)).andReturn("long 0");
+        expect(mock.oneArg(anyLong())).andStubReturn("long 1");
+
+        expect(mock.oneArg(0.0f)).andReturn("float 0");
+        expect(mock.oneArg(anyFloat())).andStubReturn("float 1");
+
+        expect(mock.oneArg(0.0)).andReturn("double 0");
+        expect(mock.oneArg(anyDouble())).andStubReturn("double 1");
+
+        expect(mock.oneArg("Object 0")).andReturn("String 0");
+        expect(mock.oneArg((String) anyObject())).andStubReturn("String 1");
+
+        replay(mock);
+
+        assertEquals("true", mock.oneArg(true));
+        assertEquals("false", mock.oneArg(false));
+
+        assertEquals("byte 0", mock.oneArg((byte) 0));
+        assertEquals("byte 1", mock.oneArg((byte) 1));
+
+        assertEquals("short 0", mock.oneArg((short) 0));
+        assertEquals("short 1", mock.oneArg((short) 1));
+
+        assertEquals("char 0", mock.oneArg((char) 0));
+        assertEquals("char 1", mock.oneArg((char) 1));
+
+        assertEquals("int 0", mock.oneArg(0));
+        assertEquals("int 1", mock.oneArg(1));
+
+        assertEquals("long 0", mock.oneArg((long) 0));
+        assertEquals("long 1", mock.oneArg((long) 1));
+
+        assertEquals("float 0", mock.oneArg((float) 0.0));
+        assertEquals("float 1", mock.oneArg((float) 1.0));
+
+        assertEquals("double 0", mock.oneArg(0.0));
+        assertEquals("double 1", mock.oneArg(1.0));
+
+        assertEquals("String 0", mock.oneArg("Object 0"));
+        assertEquals("String 1", mock.oneArg("Object 1"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void defaultThrowable() {
+
+        final RuntimeException expected = new RuntimeException();
+        expect(mock.oneArg((String) anyObject())).andStubThrow(expected);
+
+        replay(mock);
+
+        try {
+            mock.oneArg("Something else");
+            fail("runtime exception expected");
+        } catch (final RuntimeException expectedException) {
+            assertSame(expected, expectedException);
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/UsageOverloadedMethodTest.java b/tests/org/easymock/tests/UsageOverloadedMethodTest.java
index 9692a50..46ae595 100644
--- a/tests/org/easymock/tests/UsageOverloadedMethodTest.java
+++ b/tests/org/easymock/tests/UsageOverloadedMethodTest.java
@@ -1,165 +1,154 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageOverloadedMethodTest {
-
-    MockControl<IMethods> controller;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        controller = MockControl.createControl(IMethods.class);
-        mock = controller.getMock();
-    }
-
-    @Test
-    public void overloading() {
-
-        mock.oneArg(true);
-        controller.setReturnValue("true");
-        mock.oneArg(false);
-        controller.setReturnValue("false");
-
-        mock.oneArg((byte) 0);
-        controller.setReturnValue("byte 0");
-        mock.oneArg((byte) 1);
-        controller.setReturnValue("byte 1");
-
-        mock.oneArg((short) 0);
-        controller.setReturnValue("short 0");
-        mock.oneArg((short) 1);
-        controller.setReturnValue("short 1");
-
-        mock.oneArg((char) 0);
-        controller.setReturnValue("char 0");
-        mock.oneArg((char) 1);
-        controller.setReturnValue("char 1");
-
-        mock.oneArg(0);
-        controller.setReturnValue("int 0");
-        mock.oneArg(1);
-        controller.setReturnValue("int 1");
-
-        mock.oneArg((long) 0);
-        controller.setReturnValue("long 0");
-        mock.oneArg((long) 1);
-        controller.setReturnValue("long 1");
-
-        mock.oneArg((float) 0);
-        controller.setReturnValue("float 0");
-        mock.oneArg((float) 1);
-        controller.setReturnValue("float 1");
-
-        mock.oneArg(0.0);
-        controller.setReturnValue("double 0");
-        mock.oneArg(1.0);
-        controller.setReturnValue("double 1");
-
-        mock.oneArg("Object 0");
-        controller.setReturnValue("1");
-        mock.oneArg("Object 1");
-        controller.setReturnValue("2");
-
-        controller.replay();
-
-        assertEquals("true", mock.oneArg(true));
-        assertEquals("false", mock.oneArg(false));
-
-        assertEquals("byte 0", mock.oneArg((byte) 0));
-        assertEquals("byte 1", mock.oneArg((byte) 1));
-
-        assertEquals("short 0", mock.oneArg((short) 0));
-        assertEquals("short 1", mock.oneArg((short) 1));
-
-        assertEquals("char 0", mock.oneArg((char) 0));
-        assertEquals("char 1", mock.oneArg((char) 1));
-
-        assertEquals("int 0", mock.oneArg(0));
-        assertEquals("int 1", mock.oneArg(1));
-
-        assertEquals("long 0", mock.oneArg((long) 0));
-        assertEquals("long 1", mock.oneArg((long) 1));
-
-        assertEquals("float 0", mock.oneArg((float) 0.0));
-        assertEquals("float 1", mock.oneArg((float) 1.0));
-
-        assertEquals("double 1", mock.oneArg(1.0));
-        assertEquals("double 0", mock.oneArg(0.0));
-
-        assertEquals("1", mock.oneArg("Object 0"));
-        assertEquals("2", mock.oneArg("Object 1"));
-
-        controller.verify();
-    }
-
-    @Test
-    public void nullReturnValue() {
-
-        mock.oneArg("Object");
-        controller.setReturnValue(null);
-
-        controller.replay();
-
-        assertNull(mock.oneArg("Object"));
-
-    }
-
-    @Test
-    public void moreThanOneResultAndOpenCallCount() {
-        mock.oneArg(true);
-        controller.setReturnValue("First Result", 4);
-        controller.setReturnValue("Second Result", 2);
-        controller.setThrowable(new RuntimeException("Third Result"), 3);
-        controller.setReturnValue("Following Result", MockControl.ONE_OR_MORE);
-
-        controller.replay();
-
-        assertEquals("First Result", mock.oneArg(true));
-        assertEquals("First Result", mock.oneArg(true));
-        assertEquals("First Result", mock.oneArg(true));
-        assertEquals("First Result", mock.oneArg(true));
-
-        assertEquals("Second Result", mock.oneArg(true));
-        assertEquals("Second Result", mock.oneArg(true));
-
-        try {
-            mock.oneArg(true);
-            fail("expected exception");
-        } catch (RuntimeException expected) {
-            assertEquals("Third Result", expected.getMessage());
-        }
-
-        try {
-            mock.oneArg(true);
-            fail("expected exception");
-        } catch (RuntimeException expected) {
-            assertEquals("Third Result", expected.getMessage());
-        }
-
-        try {
-            mock.oneArg(true);
-            fail("expected exception");
-        } catch (RuntimeException expected) {
-            assertEquals("Third Result", expected.getMessage());
-        }
-
-        assertEquals("Following Result", mock.oneArg(true));
-        assertEquals("Following Result", mock.oneArg(true));
-        assertEquals("Following Result", mock.oneArg(true));
-        assertEquals("Following Result", mock.oneArg(true));
-        assertEquals("Following Result", mock.oneArg(true));
-
-        controller.verify();
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageOverloadedMethodTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void overloading() {
+
+        expect(mock.oneArg(true)).andReturn("true");
+        expect(mock.oneArg(false)).andReturn("false");
+
+        expect(mock.oneArg((byte) 0)).andReturn("byte 0");
+        expect(mock.oneArg((byte) 1)).andReturn("byte 1");
+
+        expect(mock.oneArg((short) 0)).andReturn("short 0");
+        expect(mock.oneArg((short) 1)).andReturn("short 1");
+
+        expect(mock.oneArg((char) 0)).andReturn("char 0");
+        expect(mock.oneArg((char) 1)).andReturn("char 1");
+
+        expect(mock.oneArg(0)).andReturn("int 0");
+        expect(mock.oneArg(1)).andReturn("int 1");
+
+        expect(mock.oneArg((long) 0)).andReturn("long 0");
+        expect(mock.oneArg((long) 1)).andReturn("long 1");
+
+        expect(mock.oneArg((float) 0)).andReturn("float 0");
+        expect(mock.oneArg((float) 1)).andReturn("float 1");
+
+        expect(mock.oneArg(0.0)).andReturn("double 0");
+        expect(mock.oneArg(1.0)).andReturn("double 1");
+
+        expect(mock.oneArg("Object 0")).andReturn("1");
+        expect(mock.oneArg("Object 1")).andReturn("2");
+
+        replay(mock);
+
+        assertEquals("true", mock.oneArg(true));
+        assertEquals("false", mock.oneArg(false));
+
+        assertEquals("byte 0", mock.oneArg((byte) 0));
+        assertEquals("byte 1", mock.oneArg((byte) 1));
+
+        assertEquals("short 0", mock.oneArg((short) 0));
+        assertEquals("short 1", mock.oneArg((short) 1));
+
+        assertEquals("char 0", mock.oneArg((char) 0));
+        assertEquals("char 1", mock.oneArg((char) 1));
+
+        assertEquals("int 0", mock.oneArg(0));
+        assertEquals("int 1", mock.oneArg(1));
+
+        assertEquals("long 0", mock.oneArg((long) 0));
+        assertEquals("long 1", mock.oneArg((long) 1));
+
+        assertEquals("float 0", mock.oneArg((float) 0.0));
+        assertEquals("float 1", mock.oneArg((float) 1.0));
+
+        assertEquals("double 1", mock.oneArg(1.0));
+        assertEquals("double 0", mock.oneArg(0.0));
+
+        assertEquals("1", mock.oneArg("Object 0"));
+        assertEquals("2", mock.oneArg("Object 1"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void nullReturnValue() {
+
+        expect(mock.oneArg("Object")).andReturn(null);
+
+        replay(mock);
+
+        assertNull(mock.oneArg("Object"));
+
+    }
+
+    @Test
+    public void moreThanOneResultAndOpenCallCount() {
+        expect(mock.oneArg(true)).andReturn("First Result").times(4).andReturn("Second Result").times(2)
+                .andThrow(new RuntimeException("Third Result")).times(3).andReturn("Following Result")
+                .atLeastOnce();
+
+        replay(mock);
+
+        assertEquals("First Result", mock.oneArg(true));
+        assertEquals("First Result", mock.oneArg(true));
+        assertEquals("First Result", mock.oneArg(true));
+        assertEquals("First Result", mock.oneArg(true));
+
+        assertEquals("Second Result", mock.oneArg(true));
+        assertEquals("Second Result", mock.oneArg(true));
+
+        try {
+            mock.oneArg(true);
+            fail("expected exception");
+        } catch (final RuntimeException expected) {
+            assertEquals("Third Result", expected.getMessage());
+        }
+
+        try {
+            mock.oneArg(true);
+            fail("expected exception");
+        } catch (final RuntimeException expected) {
+            assertEquals("Third Result", expected.getMessage());
+        }
+
+        try {
+            mock.oneArg(true);
+            fail("expected exception");
+        } catch (final RuntimeException expected) {
+            assertEquals("Third Result", expected.getMessage());
+        }
+
+        assertEquals("Following Result", mock.oneArg(true));
+        assertEquals("Following Result", mock.oneArg(true));
+        assertEquals("Following Result", mock.oneArg(true));
+        assertEquals("Following Result", mock.oneArg(true));
+        assertEquals("Following Result", mock.oneArg(true));
+
+        verify(mock);
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/UsageRangeTest.java b/tests/org/easymock/tests/UsageRangeTest.java
index f9c7029..af38f74 100644
--- a/tests/org/easymock/tests/UsageRangeTest.java
+++ b/tests/org/easymock/tests/UsageRangeTest.java
@@ -1,106 +1,97 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.util.Iterator;
-
-import org.easymock.MockControl;
-import org.easymock.internal.Range;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageRangeTest {
-
-    private Iterator<String> mock;
-
-    private MockControl<Iterator<String>> control;
-
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setup() {
-        control = MockControl.createStrictControl((Class)Iterator.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void zeroOrMoreNoCalls() {
-        mock.hasNext();
-        control.setReturnValue(false, MockControl.ZERO_OR_MORE);
-        control.replay();
-        control.verify();
-    }
-
-    @Test
-    public void zeroOrMoreOneCall() {
-        mock.hasNext();
-        control.setReturnValue(false, MockControl.ZERO_OR_MORE);
-        control.replay();
-        assertFalse(mock.hasNext());
-        control.verify();
-    }
-
-    @Test
-    public void zeroOrMoreThreeCalls() {
-        mock.hasNext();
-        control.setReturnValue(false, MockControl.ZERO_OR_MORE);
-        control.replay();
-        assertFalse(mock.hasNext());
-        assertFalse(mock.hasNext());
-        assertFalse(mock.hasNext());
-        control.verify();
-    }
-
-    @Test
-    public void combination() {
-        mock.hasNext();
-        control.setReturnValue(true, MockControl.ONE_OR_MORE);
-        mock.next();
-        control.setReturnValue("1");
-
-        mock.hasNext();
-        control.setReturnValue(true, MockControl.ONE_OR_MORE);
-        mock.next();
-        control.setReturnValue("2");
-
-        mock.hasNext();
-        control.setReturnValue(false, MockControl.ONE_OR_MORE);
-
-        control.replay();
-
-        assertTrue(mock.hasNext());
-        assertTrue(mock.hasNext());
-        assertTrue(mock.hasNext());
-
-        assertEquals("1", mock.next());
-
-        try {
-            mock.next();
-            fail();
-        } catch (AssertionError expected) {
-        }
-
-        assertTrue(mock.hasNext());
-
-        assertEquals("2", mock.next());
-
-        assertFalse(mock.hasNext());
-
-        control.verify();
-
-    }
-
-    @Test
-    public void withIllegalOwnRange() {
-        mock.hasNext();
-        try {
-            control.setReturnValue(true, new Range(2, 7));
-        } catch (IllegalArgumentException e) {
-            assertEquals("Unexpected Range", e.getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Iterator;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageRangeTest {
+
+    private Iterator<String> mock;
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setup() {
+        mock = createStrictMock(Iterator.class);
+    }
+
+    @Test
+    public void zeroOrMoreNoCalls() {
+        expect(mock.hasNext()).andReturn(false).anyTimes();
+        replay(mock);
+        verify(mock);
+    }
+
+    @Test
+    public void zeroOrMoreOneCall() {
+        expect(mock.hasNext()).andReturn(false).anyTimes();
+        replay(mock);
+        assertFalse(mock.hasNext());
+        verify(mock);
+    }
+
+    @Test
+    public void zeroOrMoreThreeCalls() {
+        expect(mock.hasNext()).andReturn(false).anyTimes();
+        replay(mock);
+        assertFalse(mock.hasNext());
+        assertFalse(mock.hasNext());
+        assertFalse(mock.hasNext());
+        verify(mock);
+    }
+
+    @Test
+    public void combination() {
+        expect(mock.hasNext()).andReturn(true).atLeastOnce();
+        expect(mock.next()).andReturn("1");
+
+        expect(mock.hasNext()).andReturn(true).atLeastOnce();
+        expect(mock.next()).andReturn("2");
+
+        expect(mock.hasNext()).andReturn(false).atLeastOnce();
+
+        replay(mock);
+
+        assertTrue(mock.hasNext());
+        assertTrue(mock.hasNext());
+        assertTrue(mock.hasNext());
+
+        assertEquals("1", mock.next());
+
+        try {
+            mock.next();
+            fail();
+        } catch (final AssertionError expected) {
+        }
+
+        assertTrue(mock.hasNext());
+
+        assertEquals("2", mock.next());
+
+        assertFalse(mock.hasNext());
+
+        verify(mock);
+
+    }
+}
diff --git a/tests/org/easymock/tests/UsageStrictMockTest.java b/tests/org/easymock/tests/UsageStrictMockTest.java
index 1e133e8..2d0d3bf 100644
--- a/tests/org/easymock/tests/UsageStrictMockTest.java
+++ b/tests/org/easymock/tests/UsageStrictMockTest.java
@@ -1,239 +1,232 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.easymock.internal.ReplayState;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageStrictMockTest {
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createStrictControl(IMethods.class);
-        mock = control.getMock();
-
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        control.replay();
-    }
-
-    @Test
-    public void verify() {
-        control.reset();
-        control.replay();
-        control.verify();
-    }
-
-    @Test
-    public void orderedCallsSucces() {
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        control.verify();
-    }
-
-    @Test
-    public void unorderedCallsFailure() {
-        boolean failed = false;
-        try {
-            mock.simpleMethodWithArgument("2");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail("unordered calls accepted");
-        }
-    }
-
-    @Test
-    public void tooManyCallsFailure() {
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        boolean failed = false;
-        try {
-            mock.simpleMethodWithArgument("2");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail("too many calls accepted");
-        }
-    }
-
-    @Test
-    public void tooFewCallsFailure() {
-        mock.simpleMethodWithArgument("1");
-        boolean failed = false;
-        try {
-            control.verify();
-        } catch (AssertionError expected) {
-            failed = true;
-            assertTrue("stack trace must be filled in", Util.getStackTrace(
-                    expected).indexOf(ReplayState.class.getName()) == -1);
-        }
-        if (!failed) {
-            fail("too few calls accepted");
-        }
-    }
-
-    @Test
-    public void differentMethods() {
-
-        control.reset();
-
-        mock.booleanReturningMethod(0);
-        control.setReturnValue(true);
-        mock.simpleMethod();
-        mock.booleanReturningMethod(1);
-        control.setReturnValue(false, 2, 3);
-        mock.simpleMethod();
-        control.setVoidCallable(MockControl.ONE_OR_MORE);
-
-        control.replay();
-        assertEquals(true, mock.booleanReturningMethod(0));
-        mock.simpleMethod();
-
-        boolean failed = false;
-        try {
-            control.verify();
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    simpleMethod(): expected: 1, actual: 1"
-                            + "\n    booleanReturningMethod(1): expected: between 2 and 3, actual: 0"
-                            + "\n    simpleMethod(): expected: at least 1, actual: 0",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("too few calls accepted");
-        }
-
-        assertEquals(false, mock.booleanReturningMethod(1));
-
-        failed = false;
-        try {
-            mock.simpleMethod();
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Unexpected method call simpleMethod():"
-                            + "\n    booleanReturningMethod(1): expected: between 2 and 3, actual: 1",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("wrong call accepted");
-        }
-    }
-
-    @Test
-    public void range() {
-
-        control.reset();
-
-        mock.booleanReturningMethod(0);
-        control.setReturnValue(true);
-        mock.simpleMethod();
-        mock.booleanReturningMethod(1);
-        control.setReturnValue(false, 2, 3);
-        mock.simpleMethod();
-        control.setVoidCallable(MockControl.ONE_OR_MORE);
-        mock.booleanReturningMethod(1);
-        control.setReturnValue(false);
-
-        control.replay();
-
-        mock.booleanReturningMethod(0);
-        mock.simpleMethod();
-
-        mock.booleanReturningMethod(1);
-        mock.booleanReturningMethod(1);
-        mock.booleanReturningMethod(1);
-
-        boolean failed = false;
-
-        try {
-            mock.booleanReturningMethod(1);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Unexpected method call booleanReturningMethod(1):"
-                            + "\n    booleanReturningMethod(1): expected: between 2 and 3, actual: 3 (+1)"
-                            + "\n    simpleMethod(): expected: at least 1, actual: 0",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("too many calls accepted");
-        }
-    }
-
-    @Test
-    public void defaultBehavior() {
-        control.reset();
-
-        mock.booleanReturningMethod(1);
-        control.setReturnValue(true);
-        control.setReturnValue(false);
-        control.setReturnValue(true);
-        control.setDefaultReturnValue(true);
-
-        control.replay();
-
-        assertEquals(true, mock.booleanReturningMethod(2));
-        assertEquals(true, mock.booleanReturningMethod(3));
-        assertEquals(true, mock.booleanReturningMethod(1));
-        assertEquals(false, mock.booleanReturningMethod(1));
-        assertEquals(true, mock.booleanReturningMethod(3));
-
-        boolean failed = false;
-        try {
-            control.verify();
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    booleanReturningMethod(1): expected: 3, actual: 2",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("too few calls accepted");
-        }
-    }
-
-    @Test
-    public void unexpectedCallWithArray() {
-        control.reset();
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-        mock.arrayMethod(new String[] { "Test", "Test 2" });
-        control.replay();
-        boolean failed = false;
-        String[] strings = new String[] { "Test" };
-        try {
-            mock.arrayMethod(strings);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Unexpected method call arrayMethod("
-                            + strings.toString()
-                            + "):"
-                            + "\n    arrayMethod([\"Test\", \"Test 2\"]): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("exception expected");
-        }
-
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.internal.ReplayState;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageStrictMockTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createStrictMock(IMethods.class);
+
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        replay(mock);
+    }
+
+    @Test
+    public void testVerify() {
+        reset(mock);
+        replay(mock);
+        verify(mock);
+    }
+
+    @Test
+    public void orderedCallsSucces() {
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        verify(mock);
+    }
+
+    @Test
+    public void unorderedCallsFailure() {
+        boolean failed = false;
+        try {
+            mock.simpleMethodWithArgument("2");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail("unordered calls accepted");
+        }
+    }
+
+    @Test
+    public void tooManyCallsFailure() {
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        boolean failed = false;
+        try {
+            mock.simpleMethodWithArgument("2");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail("too many calls accepted");
+        }
+    }
+
+    @Test
+    public void tooFewCallsFailure() {
+        mock.simpleMethodWithArgument("1");
+        boolean failed = false;
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertTrue("stack trace must be filled in", Util.getStackTrace(expected).indexOf(
+                    ReplayState.class.getName()) == -1);
+        }
+        if (!failed) {
+            fail("too few calls accepted");
+        }
+    }
+
+    @Test
+    public void differentMethods() {
+
+        reset(mock);
+
+        expect(mock.booleanReturningMethod(0)).andReturn(true);
+        mock.simpleMethod();
+        expect(mock.booleanReturningMethod(1)).andReturn(false).times(2, 3);
+        mock.simpleMethod();
+        expectLastCall().atLeastOnce();
+
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(0));
+        mock.simpleMethod();
+
+        boolean failed = false;
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.simpleMethod(): expected: 1, actual: 1"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: between 2 and 3, actual: 0"
+                    + "\n    IMethods.simpleMethod(): expected: at least 1, actual: 0", expected.getMessage());
+        }
+        if (!failed) {
+            fail("too few calls accepted");
+        }
+
+        assertEquals(false, mock.booleanReturningMethod(1));
+
+        failed = false;
+        try {
+            mock.simpleMethod();
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Unexpected method call IMethods.simpleMethod():"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: between 2 and 3, actual: 1",
+                    expected.getMessage());
+        }
+        if (!failed) {
+            fail("wrong call accepted");
+        }
+    }
+
+    @Test
+    public void range() {
+
+        reset(mock);
+
+        expect(mock.booleanReturningMethod(0)).andReturn(true);
+        mock.simpleMethod();
+        expect(mock.booleanReturningMethod(1)).andReturn(false).times(2, 3);
+        mock.simpleMethod();
+        expectLastCall().atLeastOnce();
+        expect(mock.booleanReturningMethod(1)).andReturn(false);
+
+        replay(mock);
+
+        mock.booleanReturningMethod(0);
+        mock.simpleMethod();
+
+        mock.booleanReturningMethod(1);
+        mock.booleanReturningMethod(1);
+        mock.booleanReturningMethod(1);
+
+        boolean failed = false;
+
+        try {
+            mock.booleanReturningMethod(1);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Unexpected method call IMethods.booleanReturningMethod(1):"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: between 2 and 3, actual: 4"
+                    + "\n    IMethods.simpleMethod(): expected: at least 1, actual: 0", expected.getMessage());
+        }
+        if (!failed) {
+            fail("too many calls accepted");
+        }
+    }
+
+    @Test
+    public void defaultBehavior() {
+        reset(mock);
+
+        expect(mock.booleanReturningMethod(1)).andReturn(true).andReturn(false).andReturn(true);
+        expect(mock.booleanReturningMethod(anyInt())).andStubReturn(true);
+
+        replay(mock);
+
+        assertEquals(true, mock.booleanReturningMethod(2));
+        assertEquals(true, mock.booleanReturningMethod(3));
+        assertEquals(true, mock.booleanReturningMethod(1));
+        assertEquals(false, mock.booleanReturningMethod(1));
+        assertEquals(true, mock.booleanReturningMethod(3));
+
+        boolean failed = false;
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: 3, actual: 2", expected
+                    .getMessage());
+        }
+        if (!failed) {
+            fail("too few calls accepted");
+        }
+    }
+
+    @Test
+    public void unexpectedCallWithArray() {
+        reset(mock);
+        mock.arrayMethod(aryEq(new String[] { "Test", "Test 2" }));
+        replay(mock);
+        boolean failed = false;
+        final String[] strings = new String[] { "Test" };
+        try {
+            mock.arrayMethod(strings);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Unexpected method call IMethods.arrayMethod(" + "[\"Test\"]" + "):"
+                    + "\n    IMethods.arrayMethod([\"Test\", \"Test 2\"]): expected: 1, actual: 0", expected
+                    .getMessage());
+        }
+        if (!failed) {
+            fail("exception expected");
+        }
+
+    }
+}
diff --git a/tests/org/easymock/tests/UsageTest.java b/tests/org/easymock/tests/UsageTest.java
index 6f49c2d..89571ee 100644
--- a/tests/org/easymock/tests/UsageTest.java
+++ b/tests/org/easymock/tests/UsageTest.java
@@ -1,217 +1,207 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageTest {
-
-    MockControl<IMethods> control;
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void exactCallCountByLastCall() {
-        mock.oneArg(false);
-        control.setReturnValue("Test");
-        control.setReturnValue("Test2");
-
-        control.replay();
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-
-        boolean failed = false;
-        try {
-            mock.oneArg(false);
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed)
-            fail("expected AssertionError");
-    }
-
-    @Test
-    public void openCallCountByLastCall() {
-        mock.oneArg(false);
-        control.setReturnValue("Test");
-        control.setReturnValue("Test2", MockControl.ONE_OR_MORE);
-
-        control.replay();
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-    }
-
-    @Test
-    public void exactCallCountByLastThrowable() {
-        mock.oneArg(false);
-        control.setReturnValue("Test");
-        control.setReturnValue("Test2");
-        control.setThrowable(new IndexOutOfBoundsException(), 1);
-
-        control.replay();
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-
-        try {
-            mock.oneArg(false);
-        } catch (IndexOutOfBoundsException expected) {
-        }
-
-        boolean failed = true;
-        try {
-            try {
-                mock.oneArg(false);
-            } catch (IndexOutOfBoundsException expected) {
-            }
-            failed = false;
-        } catch (AssertionError expected) {
-        }
-        if (!failed)
-            fail("expected AssertionError");
-    }
-
-    @Test
-    public void openCallCountByLastThrowable() {
-        mock.oneArg(false);
-        control.setReturnValue("Test");
-        control.setReturnValue("Test2");
-        control.setThrowable(new IndexOutOfBoundsException(),
-                MockControl.ONE_OR_MORE);
-
-        control.replay();
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-
-        try {
-            mock.oneArg(false);
-        } catch (IndexOutOfBoundsException expected) {
-        }
-        try {
-            mock.oneArg(false);
-        } catch (IndexOutOfBoundsException expected) {
-        }
-    }
-
-    @Test
-    public void moreThanOneArgument() {
-        mock.threeArgumentMethod(1, "2", "3");
-        control.setReturnValue("Test", 2);
-
-        control.replay();
-
-        assertEquals("Test", mock.threeArgumentMethod(1, "2", "3"));
-
-        boolean failed = true;
-        try {
-            control.verify();
-            failed = false;
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    threeArgumentMethod(1, \"2\", \"3\"): expected: 2, actual: 1",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("exception expected");
-        }
-    }
-
-    @Test
-    public void unexpectedCallWithArray() {
-        control.reset();
-        control.setDefaultMatcher(MockControl.ARRAY_MATCHER);
-        control.replay();
-        boolean failed = false;
-        String[] strings = new String[] { "Test" };
-        try {
-            mock.arrayMethod(strings);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals("\n  Unexpected method call arrayMethod("
-                    + strings.toString() + "):", expected.getMessage());
-        }
-        if (!failed) {
-            fail("exception expected");
-        }
-
-    }
-
-    @Test
-    public void wrongArguments() {
-        mock.simpleMethodWithArgument("3");
-        control.replay();
-
-        try {
-            mock.simpleMethodWithArgument("5");
-            fail();
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call simpleMethodWithArgument(\"5\"):"
-                            + "\n    simpleMethodWithArgument(\"3\"): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void summarizeSameObjectArguments() {
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("3");
-        control.replay();
-
-        try {
-            mock.simpleMethodWithArgument("5");
-            fail();
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call simpleMethodWithArgument(\"5\"):"
-                            + "\n    simpleMethodWithArgument(\"3\"): expected: 2, actual: 0",
-                    expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void argumentsOrdered() {
-        mock.simpleMethodWithArgument("4");
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("2");
-        mock.simpleMethodWithArgument("0");
-        mock.simpleMethodWithArgument("1");
-        control.replay();
-
-        try {
-            mock.simpleMethodWithArgument("5");
-            fail();
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call simpleMethodWithArgument(\"5\"):"
-                            + "\n    simpleMethodWithArgument(\"4\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"3\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"2\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"0\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"1\"): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-
-    }
-
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void exactCallCountByLastCall() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2");
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+
+        boolean failed = false;
+        try {
+            mock.oneArg(false);
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed)
+            fail("expected AssertionError");
+    }
+
+    @Test
+    public void openCallCountByLastCall() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2").atLeastOnce();
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+    }
+
+    @Test
+    public void exactCallCountByLastThrowable() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2").andThrow(
+                new IndexOutOfBoundsException()).once();
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+
+        try {
+            mock.oneArg(false);
+        } catch (final IndexOutOfBoundsException expected) {
+        }
+
+        boolean failed = true;
+        try {
+            try {
+                mock.oneArg(false);
+            } catch (final IndexOutOfBoundsException expected) {
+            }
+            failed = false;
+        } catch (final AssertionError expected) {
+        }
+        if (!failed)
+            fail("expected AssertionError");
+    }
+
+    @Test
+    public void openCallCountByLastThrowable() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2").andThrow(
+                new IndexOutOfBoundsException()).atLeastOnce();
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+
+        try {
+            mock.oneArg(false);
+        } catch (final IndexOutOfBoundsException expected) {
+        }
+        try {
+            mock.oneArg(false);
+        } catch (final IndexOutOfBoundsException expected) {
+        }
+    }
+
+    @Test
+    public void moreThanOneArgument() {
+        expect(mock.threeArgumentMethod(1, "2", "3")).andReturn("Test").times(2);
+
+        replay(mock);
+
+        assertEquals("Test", mock.threeArgumentMethod(1, "2", "3"));
+
+        boolean failed = true;
+        try {
+            verify(mock);
+            failed = false;
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.threeArgumentMethod(1, \"2\", \"3\"): expected: 2, actual: 1", expected
+                    .getMessage());
+        }
+        if (!failed) {
+            fail("exception expected");
+        }
+    }
+
+    @Test
+    public void unexpectedCallWithArray() {
+        reset(mock);
+        replay(mock);
+        final String[] strings = new String[] { "Test" };
+        try {
+            mock.arrayMethod(strings);
+            fail("exception expected");
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.arrayMethod(" + "[\"Test\"]" + "):", expected
+                    .getMessage());
+        }
+    }
+
+    @Test
+    public void wrongArguments() {
+        mock.simpleMethodWithArgument("3");
+        replay(mock);
+
+        try {
+            mock.simpleMethodWithArgument("5");
+            fail();
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.simpleMethodWithArgument(\"5\"):"
+                    + "\n    IMethods.simpleMethodWithArgument(\"3\"): expected: 1, actual: 0", expected
+                    .getMessage());
+        }
+
+    }
+
+    @Test
+    public void summarizeSameObjectArguments() {
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("3");
+        replay(mock);
+
+        try {
+            mock.simpleMethodWithArgument("5");
+            fail();
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.simpleMethodWithArgument(\"5\"):"
+                    + "\n    IMethods.simpleMethodWithArgument(\"3\"): expected: 2, actual: 0", expected
+                    .getMessage());
+        }
+
+    }
+
+    @Test
+    public void argumentsOrdered() {
+        mock.simpleMethodWithArgument("4");
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("2");
+        mock.simpleMethodWithArgument("0");
+        mock.simpleMethodWithArgument("1");
+        replay(mock);
+
+        try {
+            mock.simpleMethodWithArgument("5");
+            fail();
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.simpleMethodWithArgument(\"5\"):"
+                    + "\n    IMethods.simpleMethodWithArgument(\"4\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"3\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"2\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"0\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"1\"): expected: 1, actual: 0", expected
+                    .getMessage());
+        }
+
+    }
+
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/UsageThrowableTest.java b/tests/org/easymock/tests/UsageThrowableTest.java
index a6fc3be..503189b 100644
--- a/tests/org/easymock/tests/UsageThrowableTest.java
+++ b/tests/org/easymock/tests/UsageThrowableTest.java
@@ -1,143 +1,145 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageThrowableTest {
-
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void noUpperLimit() {
-        mock.simpleMethodWithArgument("1");
-        control.setVoidCallable(MockControl.ONE_OR_MORE);
-        mock.simpleMethodWithArgument("2");
-        control.replay();
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("1");
-        control.verify();
-    }
-
-    @Test
-    public void throwRuntimeException() {
-        testThrowUncheckedException(new RuntimeException());
-    }
-
-    @Test
-    public void throwSubclassOfRuntimeException() {
-        testThrowUncheckedException(new RuntimeException() {
-            private static final long serialVersionUID = 1L;
-        });
-    }
-
-    @Test
-    public void throwError() {
-        testThrowUncheckedException(new Error());
-    }
-
-    @Test
-    public void throwSubclassOfError() {
-        testThrowUncheckedException(new Error() {
-            private static final long serialVersionUID = 1L;
-        });
-    }
-
-    private void testThrowUncheckedException(Throwable throwable) {
-        mock.throwsNothing(true);
-        control.setReturnValue("true");
-        mock.throwsNothing(false);
-        control.setThrowable(throwable);
-
-        control.replay();
-
-        try {
-            mock.throwsNothing(false);
-            fail("Trowable expected");
-        } catch (Throwable expected) {
-            assertSame(throwable, expected);
-        }
-
-        assertEquals("true", mock.throwsNothing(true));
-    }
-
-    @Test
-    public void throwCheckedException() throws IOException {
-        testThrowCheckedException(new IOException());
-    }
-
-    @Test
-    public void throwSubclassOfCheckedException() throws IOException {
-        testThrowCheckedException(new IOException() {
-            private static final long serialVersionUID = 1L;
-        });
-    }
-
-    private void testThrowCheckedException(IOException expected)
-            throws IOException {
-        try {
-            mock.throwsIOException(0);
-            control.setReturnValue("Value 0");
-            mock.throwsIOException(1);
-            control.setThrowable(expected);
-            mock.throwsIOException(2);
-            control.setReturnValue("Value 2");
-        } catch (IOException e) {
-            fail("Unexpected Exception");
-        }
-
-        control.replay();
-
-        assertEquals("Value 0", mock.throwsIOException(0));
-        assertEquals("Value 2", mock.throwsIOException(2));
-
-        try {
-            mock.throwsIOException(1);
-            fail("IOException expected");
-        } catch (IOException expectedException) {
-            assertSame(expectedException, expected);
-        }
-    }
-
-    @Test
-    public void throwAfterReturnValue() {
-        mock.throwsNothing(false);
-        control.setReturnValue("");
-        RuntimeException expectedException = new RuntimeException();
-        control.setThrowable(expectedException);
-
-        control.replay();
-
-        assertEquals("", mock.throwsNothing(false));
-
-        try {
-            mock.throwsNothing(false);
-            fail("RuntimeException expected");
-        } catch (RuntimeException actualException) {
-            assertSame(expectedException, actualException);
-        }
-
-        control.verify();
-    }
-
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageThrowableTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void noUpperLimit() {
+        mock.simpleMethodWithArgument("1");
+        expectLastCall().atLeastOnce();
+        mock.simpleMethodWithArgument("2");
+        replay(mock);
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("1");
+        verify(mock);
+    }
+
+    @Test
+    public void throwRuntimeException() {
+        testThrowUncheckedException(new RuntimeException());
+    }
+
+    @Test
+    public void throwSubclassOfRuntimeException() {
+        testThrowUncheckedException(new RuntimeException() {
+            private static final long serialVersionUID = 1L;
+        });
+    }
+
+    @Test
+    public void throwError() {
+        testThrowUncheckedException(new Error());
+    }
+
+    @Test
+    public void throwSubclassOfError() {
+        testThrowUncheckedException(new Error() {
+            private static final long serialVersionUID = 1L;
+        });
+    }
+
+    private void testThrowUncheckedException(final Throwable throwable) {
+        expect(mock.throwsNothing(true)).andReturn("true");
+        expect(mock.throwsNothing(false)).andThrow(throwable);
+
+        replay(mock);
+
+        try {
+            mock.throwsNothing(false);
+            fail("Trowable expected");
+        } catch (final Throwable expected) {
+            assertSame(throwable, expected);
+        }
+
+        assertEquals("true", mock.throwsNothing(true));
+    }
+
+    @Test
+    public void throwCheckedException() throws IOException {
+        testThrowCheckedException(new IOException());
+    }
+
+    @Test
+    public void throwSubclassOfCheckedException() throws IOException {
+        testThrowCheckedException(new IOException() {
+            private static final long serialVersionUID = 1L;
+        });
+    }
+
+    private void testThrowCheckedException(final IOException expected) throws IOException {
+        try {
+            expect(mock.throwsIOException(0)).andReturn("Value 0");
+            expect(mock.throwsIOException(1)).andThrow(expected);
+            expect(mock.throwsIOException(2)).andReturn("Value 2");
+        } catch (final IOException e) {
+            fail("Unexpected Exception");
+        }
+
+        replay(mock);
+
+        assertEquals("Value 0", mock.throwsIOException(0));
+        assertEquals("Value 2", mock.throwsIOException(2));
+
+        try {
+            mock.throwsIOException(1);
+            fail("IOException expected");
+        } catch (final IOException expectedException) {
+            assertSame(expectedException, expected);
+        }
+    }
+
+    @Test
+    public void throwAfterReturnValue() {
+        final RuntimeException expectedException = new RuntimeException();
+        expect(mock.throwsNothing(false)).andReturn("").andThrow(expectedException);
+
+        replay(mock);
+
+        assertEquals("", mock.throwsNothing(false));
+
+        try {
+            mock.throwsNothing(false);
+            fail("RuntimeException expected");
+        } catch (final RuntimeException actualException) {
+            assertSame(expectedException, actualException);
+        }
+
+        verify(mock);
+    }
+
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/UsageUnorderedTest.java b/tests/org/easymock/tests/UsageUnorderedTest.java
index c93bd2a..86d442f 100644
--- a/tests/org/easymock/tests/UsageUnorderedTest.java
+++ b/tests/org/easymock/tests/UsageUnorderedTest.java
@@ -1,49 +1,60 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import org.easymock.MockControl;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageUnorderedTest {
-
-    public interface Interface {
-        void method(int number);
-    }
-
-    @Test
-    public void message() {
-        MockControl<Interface> control = MockControl
-                .createControl(Interface.class);
-        Interface mock = control.getMock();
-
-        mock.method(0);
-        control.setMatcher(MockControl.ALWAYS_MATCHER);
-        control.setVoidCallable(1);
-        mock.method(0);
-        control.setVoidCallable(2);
-        mock.method(1);
-
-        control.replay();
-
-        mock.method(6);
-        mock.method(7);
-        mock.method(1);
-        mock.method(25);
-
-        try {
-            mock.method(42);
-            fail();
-        } catch (AssertionError expected) {
-            assertEquals("\n  Unexpected method call method(42):"
-                    + "\n    method(<any>): expected: 3, actual: 3 (+1)"
-                    + "\n    method(<any>): expected: 1, actual: 1 (+1)",
-                    expected.getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageUnorderedTest {
+
+    public interface Interface {
+        void method(int number);
+    }
+
+    @Test
+    public void message() {
+        final Interface mock = createMock(Interface.class);
+
+        mock.method(anyInt());
+        expectLastCall().once();
+        mock.method(42);
+        mock.method(anyInt());
+        expectLastCall().times(2);
+
+        replay(mock);
+
+        mock.method(6);
+        mock.method(7);
+        mock.method(1);
+        mock.method(42);
+
+        try {
+            mock.method(42);
+            fail("Should fail");
+        } catch (final AssertionError expected) {
+            assertEquals(
+                    "\n  Unexpected method call Interface.method(42). Possible matches are marked with (+1):"
+                            + "\n    Interface.method(<any>): expected: 3, actual: 3 (+1)"
+                            + "\n    Interface.method(42): expected: 1, actual: 1 (+1)", expected
+                            .getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/UsageVarargTest.java b/tests/org/easymock/tests/UsageVarargTest.java
index df84c68..89a83b3 100644
--- a/tests/org/easymock/tests/UsageVarargTest.java
+++ b/tests/org/easymock/tests/UsageVarargTest.java
@@ -1,149 +1,195 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-
-import org.easymock.MockControl;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageVarargTest {
-
-    MockControl<IVarArgs> control;
-
-    IVarArgs mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createStrictControl(IVarArgs.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void varargObjectAccepted() {
-        mock.withVarargsString(1, "1");
-        mock.withVarargsString(2, "1", "2");
-        mock.withVarargsString(2, "1", "2");
-        mock.withVarargsObject(3, "1");
-        mock.withVarargsObject(4, "1", "2");
-
-        control.replay();
-        mock.withVarargsString(1, "1");
-        mock.withVarargsString(2, "1", "2");
-        mock.withVarargsString(2, "1", "2");
-        mock.withVarargsObject(3, "1");
-        mock.withVarargsObject(4, "1", "2");
-        control.verify();
-    }
-
-    @Test
-    public void varargBooleanAccepted() {
-        mock.withVarargsBoolean(1, true);
-        mock.withVarargsBoolean(2, true, false);
-
-        control.replay();
-        mock.withVarargsBoolean(1, true);
-        mock.withVarargsBoolean(2, true, false);
-        control.verify();
-    }
-
-    @Test
-    public void varargByteAccepted() {
-        mock.withVarargsByte(1, (byte) 1);
-        mock.withVarargsByte(2, (byte) 1, (byte) 2);
-
-        control.replay();
-        mock.withVarargsByte(1, (byte) 1);
-        mock.withVarargsByte(2, (byte) 1, (byte) 2);
-        control.verify();
-    }
-
-    @Test
-    public void varargCharAccepted() {
-        mock.withVarargsChar(1, 'a');
-        mock.withVarargsChar(1, 'a', 'b');
-
-        control.replay();
-        mock.withVarargsChar(1, 'a');
-        mock.withVarargsChar(1, 'a', 'b');
-        control.verify();
-    }
-
-    @Test
-    public void varargDoubleAccepted() {
-        mock.withVarargsDouble(1, 1.0d);
-        mock.withVarargsDouble(1, 1.0d, 2.0d);
-
-        control.replay();
-        mock.withVarargsDouble(1, 1.0d);
-        mock.withVarargsDouble(1, 1.0d, 2.0d);
-        control.verify();
-    }
-
-    @Test
-    public void varargFloatAccepted() {
-        mock.withVarargsFloat(1, 1.0f);
-        mock.withVarargsFloat(1, 1.0f, 2.0f);
-
-        control.replay();
-        mock.withVarargsFloat(1, 1.0f);
-        mock.withVarargsFloat(1, 1.0f, 2.0f);
-        control.verify();
-    }
-
-    @Test
-    public void varargIntAccepted() {
-        mock.withVarargsInt(1, 1);
-        mock.withVarargsInt(1, 1, 2);
-
-        control.replay();
-        mock.withVarargsInt(1, 1);
-        mock.withVarargsInt(1, 1, 2);
-        control.verify();
-    }
-
-    @Test
-    public void varargLongAccepted() {
-        mock.withVarargsLong(1, (long) 1);
-        mock.withVarargsLong(1, 1, 2);
-
-        control.replay();
-        mock.withVarargsLong(1, (long) 1);
-        mock.withVarargsLong(1, 1, 2);
-        control.verify();
-    }
-
-    @Test
-    public void varargShortAccepted() {
-        mock.withVarargsShort(1, (short) 1);
-        mock.withVarargsShort(1, (short) 1, (short) 2);
-
-        control.replay();
-        mock.withVarargsShort(1, (short) 1);
-        mock.withVarargsShort(1, (short) 1, (short) 2);
-        control.verify();
-    }
-    
-    @Test
-    public void varargAcceptedIfArrayIsGiven() {
-        IVarArgs object = (IVarArgs) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] { IVarArgs.class }, new InvocationHandler() {
-        
-            public Object invoke(Object proxy, Method method, Object[] args)
-                    throws Throwable {
-                return null;
-            }
-        });
-        object.withVarargsObject(1);
-        object.withVarargsObject(1, (Object) null);
-        object.withVarargsObject(1, (Object[]) null);
-        object.withVarargsObject(1, (Object[]) new Object[0] );
-        object.withVarargsObject(1, false);
-        object.withVarargsObject(1, new boolean[] {true, false});
-    }
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageVarargTest {
+
+    private IVarArgs mock;
+
+    @Before
+    public void setup() {
+        mock = createStrictMock(IVarArgs.class);
+    }
+
+    @Test
+    public void varargObjectAccepted() {
+        mock.withVarargsString(1, "1");
+        mock.withVarargsString(2, "1", "2");
+        mock.withVarargsString(2, "1", "2");
+        mock.withVarargsObject(3, "1");
+        mock.withVarargsObject(4, "1", "2");
+
+        replay(mock);
+        mock.withVarargsString(1, "1");
+        mock.withVarargsString(2, "1", "2");
+        mock.withVarargsString(2, "1", "2");
+        mock.withVarargsObject(3, "1");
+        mock.withVarargsObject(4, "1", "2");
+        verify(mock);
+    }
+
+    @Test
+    public void varargBooleanAccepted() {
+        mock.withVarargsBoolean(1, true);
+        mock.withVarargsBoolean(2, true, false);
+
+        replay(mock);
+        mock.withVarargsBoolean(1, true);
+        mock.withVarargsBoolean(2, true, false);
+        verify(mock);
+    }
+
+    @Test
+    public void varargByteAccepted() {
+        mock.withVarargsByte(1, (byte) 1);
+        mock.withVarargsByte(2, (byte) 1, (byte) 2);
+
+        replay(mock);
+        mock.withVarargsByte(1, (byte) 1);
+        mock.withVarargsByte(2, (byte) 1, (byte) 2);
+        verify(mock);
+    }
+
+    @Test
+    public void varargCharAccepted() {
+        mock.withVarargsChar(1, 'a');
+        mock.withVarargsChar(1, 'a', 'b');
+
+        replay(mock);
+        mock.withVarargsChar(1, 'a');
+        mock.withVarargsChar(1, 'a', 'b');
+        verify(mock);
+    }
+
+    @Test
+    public void varargDoubleAccepted() {
+        mock.withVarargsDouble(1, 1.0d);
+        mock.withVarargsDouble(1, 1.0d, 2.0d);
+
+        replay(mock);
+        mock.withVarargsDouble(1, 1.0d);
+        mock.withVarargsDouble(1, 1.0d, 2.0d);
+        verify(mock);
+    }
+
+    @Test
+    public void varargFloatAccepted() {
+        mock.withVarargsFloat(1, 1.0f);
+        mock.withVarargsFloat(1, 1.0f, 2.0f);
+
+        replay(mock);
+        mock.withVarargsFloat(1, 1.0f);
+        mock.withVarargsFloat(1, 1.0f, 2.0f);
+        verify(mock);
+    }
+
+    @Test
+    public void varargIntAccepted() {
+        mock.withVarargsInt(1, 1);
+        mock.withVarargsInt(1, 1, 2);
+
+        replay(mock);
+        mock.withVarargsInt(1, 1);
+        mock.withVarargsInt(1, 1, 2);
+        verify(mock);
+    }
+
+    @Test
+    public void varargLongAccepted() {
+        mock.withVarargsLong(1, (long) 1);
+        mock.withVarargsLong(1, 1, 2);
+
+        replay(mock);
+        mock.withVarargsLong(1, (long) 1);
+        mock.withVarargsLong(1, 1, 2);
+        verify(mock);
+    }
+
+    @Test
+    public void varargShortAccepted() {
+        mock.withVarargsShort(1, (short) 1);
+        mock.withVarargsShort(1, (short) 1, (short) 2);
+
+        replay(mock);
+        mock.withVarargsShort(1, (short) 1);
+        mock.withVarargsShort(1, (short) 1, (short) 2);
+        verify(mock);
+    }
+
+    @Test
+    public void varargAcceptedIfArrayIsGiven() {
+        final IVarArgs object = (IVarArgs) Proxy.newProxyInstance(Thread.currentThread()
+                .getContextClassLoader(), new Class[] { IVarArgs.class }, new InvocationHandler() {
+
+            public Object invoke(final Object proxy, final Method method, final Object[] args)
+                    throws Throwable {
+                return null;
+            }
+        });
+        object.withVarargsObject(1);
+        object.withVarargsObject(1, (Object) null);
+        object.withVarargsObject(1, (Object[]) null);
+        object.withVarargsObject(1, new Object[0]);
+        object.withVarargsObject(1, false);
+        object.withVarargsObject(1, new boolean[] { true, false });
+    }
+
+    /**
+     * Make sure we can validate any kind of varargs call
+     */
+    @Test
+    public void allKinds() {
+        mock.withVarargsObject(eq(1), aryEq((Object[]) null));
+        mock.withVarargsObject(eq(1), isNull());
+        mock.withVarargsObject(1, "a", "b");
+        mock.withVarargsObject(1, "a", "b");
+        mock.withVarargsObject(eq(1), aryEq(new Object[] { "a", "b" }));
+        mock.withVarargsObject(1);
+        replay(mock);
+        mock.withVarargsObject(1, (Object[]) null);
+        mock.withVarargsObject(1, (Object) null);
+        mock.withVarargsObject(1, "a", "b");
+        mock.withVarargsObject(1, new Object[] { "a", "b" });
+        mock.withVarargsObject(1, (Object) new Object[] { "a", "b" });
+        mock.withVarargsObject(1);
+        verify(mock);
+    }
+
+    @Test
+    public void differentLength() {
+        mock.withVarargsInt(1, 2, 3);
+        replay(mock);
+        try {
+            mock.withVarargsInt(1, 2);
+            fail("not the same number of params");
+        } catch (final AssertionError e) {
+
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/org/easymock/tests/UsageVerifyTest.java b/tests/org/easymock/tests/UsageVerifyTest.java
index 4072a63..ff88154 100644
--- a/tests/org/easymock/tests/UsageVerifyTest.java
+++ b/tests/org/easymock/tests/UsageVerifyTest.java
@@ -1,154 +1,151 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-
-import org.easymock.MockControl;
-import org.easymock.internal.ReplayState;
-import org.junit.Before;
-import org.junit.Test;
-
- at SuppressWarnings("deprecation")
-public class UsageVerifyTest {
-    private MockControl<IMethods> control;
-
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        control = MockControl.createControl(IMethods.class);
-        mock = control.getMock();
-    }
-
-    @Test
-    public void twoReturns() {
-        mock.throwsNothing(true);
-        control.setReturnValue("Test");
-        control.setReturnValue("Test2");
-
-        control.replay();
-
-        assertEquals("Test", mock.throwsNothing(true));
-
-        boolean failed = true;
-
-        try {
-            control.verify();
-            failed = false;
-        } catch (AssertionError expected) {
-            assertEquals("\n  Expectation failure on verify:"
-                    + "\n    throwsNothing(true): expected: 2, actual: 1",
-                    expected.getMessage());
-            assertTrue("stack trace must be filled in", Util.getStackTrace(
-                    expected).indexOf(ReplayState.class.getName()) == -1);
-        }
-
-        if (!failed)
-            fail("AssertionError expected");
-
-        assertEquals("Test2", mock.throwsNothing(true));
-
-        control.verify();
-
-        try {
-            mock.throwsNothing(true);
-            fail("AssertionError expected");
-        } catch (AssertionError expected) {
-            assertEquals("\n  Unexpected method call throwsNothing(true):"
-                    + "\n    throwsNothing(true): expected: 2, actual: 2 (+1)",
-                    expected.getMessage());
-        }
-    }
-
-    @Test
-    public void atLeastTwoReturns() {
-        mock.throwsNothing(true);
-        control.setReturnValue("Test");
-        control.setReturnValue("Test2", MockControl.ONE_OR_MORE);
-
-        control.replay();
-
-        assertEquals("Test", mock.throwsNothing(true));
-
-        try {
-            control.verify();
-            fail("AssertionError expected");
-        } catch (AssertionError expected) {
-
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    throwsNothing(true): expected: at least 2, actual: 1",
-                    expected.getMessage());
-        }
-
-        assertEquals("Test2", mock.throwsNothing(true));
-        assertEquals("Test2", mock.throwsNothing(true));
-
-        control.verify();
-    }
-
-    @Test
-    public void twoThrows() throws IOException {
-        mock.throwsIOException(0);
-        control.setThrowable(new IOException());
-        control.setThrowable(new IOException());
-        mock.throwsIOException(1);
-        control.setThrowable(new IOException());
-
-        control.replay();
-
-        try {
-            mock.throwsIOException(0);
-            fail("IOException expected");
-        } catch (IOException expected) {
-        }
-
-        try {
-            control.verify();
-            fail("AssertionError expected");
-        } catch (AssertionError expected) {
-            assertEquals("\n  Expectation failure on verify:"
-                    + "\n    throwsIOException(0): expected: 2, actual: 1"
-                    + "\n    throwsIOException(1): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-
-        try {
-            mock.throwsIOException(0);
-            fail("IOException expected");
-        } catch (IOException expected) {
-        }
-
-        try {
-            control.verify();
-            fail("AssertionError expected");
-        } catch (AssertionError expected) {
-            assertEquals("\n  Expectation failure on verify:"
-                    + "\n    throwsIOException(1): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-
-        try {
-            mock.throwsIOException(1);
-            fail("IOException expected");
-        } catch (IOException expected) {
-        }
-
-        control.verify();
-
-        try {
-            mock.throwsIOException(0);
-            fail("AssertionError expected");
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call throwsIOException(0):"
-                            + "\n    throwsIOException(0): expected: 2, actual: 2 (+1)",
-                    expected.getMessage());
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.easymock.internal.ReplayState;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageVerifyTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void twoReturns() {
+        expect(mock.throwsNothing(true)).andReturn("Test").andReturn("Test2");
+
+        replay(mock);
+
+        assertEquals("Test", mock.throwsNothing(true));
+
+        boolean failed = true;
+
+        try {
+            verify(mock);
+            failed = false;
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.throwsNothing(true): expected: 2, actual: 1", expected.getMessage());
+            assertTrue("stack trace must be filled in", Util.getStackTrace(expected).indexOf(
+                    ReplayState.class.getName()) == -1);
+        }
+
+        if (!failed)
+            fail("AssertionError expected");
+
+        assertEquals("Test2", mock.throwsNothing(true));
+
+        verify(mock);
+
+        try {
+            mock.throwsNothing(true);
+            fail("AssertionError expected");
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.throwsNothing(true):"
+                    + "\n    IMethods.throwsNothing(true): expected: 2, actual: 3", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void atLeastTwoReturns() {
+        expect(mock.throwsNothing(true)).andReturn("Test").andReturn("Test2").atLeastOnce();
+
+        replay(mock);
+
+        assertEquals("Test", mock.throwsNothing(true));
+
+        try {
+            verify(mock);
+            fail("AssertionError expected");
+        } catch (final AssertionError expected) {
+
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.throwsNothing(true): expected: at least 2, actual: 1", expected
+                    .getMessage());
+        }
+
+        assertEquals("Test2", mock.throwsNothing(true));
+        assertEquals("Test2", mock.throwsNothing(true));
+
+        verify(mock);
+    }
+
+    @Test
+    public void twoThrows() throws IOException {
+        expect(mock.throwsIOException(0)).andThrow(new IOException()).andThrow(new IOException());
+        expect(mock.throwsIOException(1)).andThrow(new IOException());
+
+        replay(mock);
+
+        try {
+            mock.throwsIOException(0);
+            fail("IOException expected");
+        } catch (final IOException expected) {
+        }
+
+        try {
+            verify(mock);
+            fail("AssertionError expected");
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.throwsIOException(0): expected: 2, actual: 1"
+                    + "\n    IMethods.throwsIOException(1): expected: 1, actual: 0", expected.getMessage());
+        }
+
+        try {
+            mock.throwsIOException(0);
+            fail("IOException expected");
+        } catch (final IOException expected) {
+        }
+
+        try {
+            verify(mock);
+            fail("AssertionError expected");
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.throwsIOException(1): expected: 1, actual: 0", expected.getMessage());
+        }
+
+        try {
+            mock.throwsIOException(1);
+            fail("IOException expected");
+        } catch (final IOException expected) {
+        }
+
+        verify(mock);
+
+        try {
+            mock.throwsIOException(0);
+            fail("AssertionError expected");
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.throwsIOException(0):"
+                    + "\n    IMethods.throwsIOException(0): expected: 2, actual: 3", expected.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests/Util.java b/tests/org/easymock/tests/Util.java
index b3fd0e7..ae8e8da 100644
--- a/tests/org/easymock/tests/Util.java
+++ b/tests/org/easymock/tests/Util.java
@@ -1,16 +1,39 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-public class Util {
-    public static String getStackTrace(Throwable throwable) {
-        StringWriter stackTrace = new StringWriter();
-        throwable.printStackTrace(new PrintWriter(stackTrace));
-        return stackTrace.getBuffer().toString();
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public final class Util {
+
+    private Util() {
+    }
+
+    public static String getStackTrace(final Throwable throwable) {
+        final StringWriter stackTrace = new StringWriter();
+        throwable.printStackTrace(new PrintWriter(stackTrace));
+        return stackTrace.getBuffer().toString();
+    }
+
+    public static boolean startWithClass(final Throwable throwable, final Class<?> clazz) {
+        final StackTraceElement[] elements = throwable.getStackTrace();
+        return elements[0].getClassName().equals(clazz.getName());
+    }
+}
diff --git a/tests/org/easymock/tests2/AnswerTest.java b/tests/org/easymock/tests2/AnswerTest.java
index c39a76f..a187654 100644
--- a/tests/org/easymock/tests2/AnswerTest.java
+++ b/tests/org/easymock/tests2/AnswerTest.java
@@ -1,148 +1,172 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.IAnswer;
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class AnswerTest {
-
-    private IMethods mock;
-
-    @Before
-    public void setUp() {
-        mock = createMock(IMethods.class);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void answer() {
-        IAnswer firstAnswer = new IAnswer() {
-            public Object answer() {
-                assertArrayEquals(new Object[] { 1, "2", "3" },
-                        getCurrentArguments());
-                return "Call answered";
-            }
-        };
-
-        IAnswer secondAnswer = new IAnswer() {
-            public Object answer() {
-                assertArrayEquals(new Object[] { 1, "2", "3" },
-                        getCurrentArguments());
-                throw new IllegalStateException("Call answered");
-            }
-        };
-
-        expect(mock.threeArgumentMethod(1, "2", "3")).andAnswer(firstAnswer)
-                .andReturn("Second call").andAnswer(secondAnswer).andReturn(
-                        "Fourth call");
-
-        replay(mock);
-
-        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
-        assertEquals("Second call", mock.threeArgumentMethod(1, "2", "3"));
-        try {
-            mock.threeArgumentMethod(1, "2", "3");
-            fail();
-        } catch (IllegalStateException expected) {
-            assertEquals("Call answered", expected.getMessage());
-        }
-        assertEquals("Fourth call", mock.threeArgumentMethod(1, "2", "3"));
-
-        verify(mock);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void stubAnswer() {
-        IAnswer firstAnswer = new IAnswer() {
-            public Object answer() {
-                assertArrayEquals(new Object[] { 1, "2", "3" },
-                        getCurrentArguments());
-                return "Call answered";
-            }
-        };
-
-        IAnswer secondAnswer = new IAnswer() {
-            public Object answer() {
-                assertArrayEquals(new Object[] { 1, "2", "4" },
-                        getCurrentArguments());
-                return "Call answered";
-            }
-        };
-
-        expect(mock.threeArgumentMethod(1, "2", "3")).andReturn(42)
-                .andStubAnswer(firstAnswer);
-        expect(mock.threeArgumentMethod(1, "2", "4")).andStubAnswer(
-                secondAnswer);
-
-        replay(mock);
-
-        assertEquals(42, mock.threeArgumentMethod(1, "2", "3"));
-        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
-        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "4"));
-        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
-        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
-
-        verify(mock);
-    }
-
-    @Test
-    public void nullAnswerNotAllowed() {
-        try {
-            expect(mock.threeArgumentMethod(1, "2", "3")).andAnswer(null);
-            fail();
-        } catch (NullPointerException expected) {
-            assertEquals("answer object must not be null", expected
-                    .getMessage());
-        }
-    }
-
-    @Test
-    public void nullStubAnswerNotAllowed() {
-        try {
-            expect(mock.threeArgumentMethod(1, "2", "3")).andStubAnswer(null);
-            fail();
-        } catch (NullPointerException expected) {
-            assertEquals("answer object must not be null", expected
-                    .getMessage());
-        }
-    }
-
-    public static class A {}
-    public static class B extends A{}
-    
-    public static interface C {
-        A foo();
-    }
-    
-    @Test
-    public void testGenericityFlexibility() {
-        
-        final C c = createMock(C.class);
-        final B b = new B();
-        
-        IAnswer<B> answer = new IAnswer<B>() {
-
-            public B answer() throws Throwable {
-                return b;
-            }
-            
-        };
-
-        expect(c.foo()).andAnswer(answer);
-        expect(c.foo()).andStubAnswer(answer);
-        
-        replay(c);
-        assertSame(b, c.foo());
-        assertSame(b, c.foo());
-        verify(c);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.IAnswer;
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class AnswerTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void answer() {
+        final IAnswer<Object> firstAnswer = new IAnswer<Object>() {
+            public Object answer() {
+                assertArrayEquals(new Object[] { 1, "2", "3" }, getCurrentArguments());
+                return "Call answered";
+            }
+        };
+
+        final IAnswer<Object> secondAnswer = new IAnswer<Object>() {
+            public Object answer() {
+                assertArrayEquals(new Object[] { 1, "2", "3" }, getCurrentArguments());
+                throw new IllegalStateException("Call answered");
+            }
+        };
+
+        expect(mock.threeArgumentMethod(1, "2", "3")).andAnswer(firstAnswer).andReturn("Second call")
+                .andAnswer(secondAnswer).andReturn("Fourth call");
+
+        replay(mock);
+
+        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
+        assertEquals("Second call", mock.threeArgumentMethod(1, "2", "3"));
+        try {
+            mock.threeArgumentMethod(1, "2", "3");
+            fail();
+        } catch (final IllegalStateException expected) {
+            assertEquals("Call answered", expected.getMessage());
+        }
+        assertEquals("Fourth call", mock.threeArgumentMethod(1, "2", "3"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void stubAnswer() {
+        final IAnswer<Object> firstAnswer = new IAnswer<Object>() {
+            public Object answer() {
+                assertArrayEquals(new Object[] { 1, "2", "3" }, getCurrentArguments());
+                return "Call answered";
+            }
+        };
+
+        final IAnswer<Object> secondAnswer = new IAnswer<Object>() {
+            public Object answer() {
+                assertArrayEquals(new Object[] { 1, "2", "4" }, getCurrentArguments());
+                return "Call answered";
+            }
+        };
+
+        expect(mock.threeArgumentMethod(1, "2", "3")).andReturn(42).andStubAnswer(firstAnswer);
+        expect(mock.threeArgumentMethod(1, "2", "4")).andStubAnswer(secondAnswer);
+
+        replay(mock);
+
+        assertEquals(42, mock.threeArgumentMethod(1, "2", "3"));
+        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
+        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "4"));
+        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
+        assertEquals("Call answered", mock.threeArgumentMethod(1, "2", "3"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void nullAnswerNotAllowed() {
+        try {
+            expect(mock.threeArgumentMethod(1, "2", "3")).andAnswer(null);
+            fail();
+        } catch (final NullPointerException expected) {
+            assertEquals("answer object must not be null", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void nullStubAnswerNotAllowed() {
+        try {
+            expect(mock.threeArgumentMethod(1, "2", "3")).andStubAnswer(null);
+            fail();
+        } catch (final NullPointerException expected) {
+            assertEquals("answer object must not be null", expected.getMessage());
+        }
+    }
+
+    public static class A {
+    }
+
+    public static class B extends A {
+    }
+
+    public static interface C {
+        A foo();
+    }
+
+    @Test
+    public void testGenericityFlexibility() {
+
+        final C c = createMock(C.class);
+        final B b = new B();
+
+        final IAnswer<B> answer = new IAnswer<B>() {
+
+            public B answer() throws Throwable {
+                return b;
+            }
+
+        };
+
+        expect(c.foo()).andAnswer(answer);
+        expect(c.foo()).andStubAnswer(answer);
+
+        replay(c);
+        assertSame(b, c.foo());
+        assertSame(b, c.foo());
+        verify(c);
+    }
+
+    @Test
+    public void answerOnVoidMethod() {
+        final String[] array = new String[] { "a" };
+        mock.arrayMethod(array);
+        expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() throws Throwable {
+                final String[] s = (String[]) getCurrentArguments()[0];
+                s[0] = "b";
+                return null;
+            }
+        });
+        replay(mock);
+        mock.arrayMethod(array);
+        verify(mock);
+
+        assertEquals("b", array[0]);
+    }
+}
diff --git a/tests/org/easymock/tests2/CallbackAndArgumentsTest.java b/tests/org/easymock/tests2/CallbackAndArgumentsTest.java
index f6b5e18..efc9b6b 100644
--- a/tests/org/easymock/tests2/CallbackAndArgumentsTest.java
+++ b/tests/org/easymock/tests2/CallbackAndArgumentsTest.java
@@ -1,86 +1,100 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.IAnswer;
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class CallbackAndArgumentsTest {
-
-    private IMethods mock;
-
-    @Before
-    public void setUp() {
-        mock = createStrictMock(IMethods.class);
-    }
-
-    @Test
-    public void callbackGetsArguments() {
-
-        final StringBuffer buffer = new StringBuffer();
-
-        mock.simpleMethodWithArgument((String) notNull());
-        expectLastCall().andAnswer(new IAnswer<Object>() {
-            public Object answer() {
-                buffer.append((String) getCurrentArguments()[0]);
-                return null;
-            }
-        }).times(2);
-
-        replay(mock);
-
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        verify(mock);
-
-        assertEquals("12", buffer.toString());
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void currentArgumentsFailsOutsideCallbacks() {
-        getCurrentArguments();
-    }
-
-    @Test
-    public void callbackGetsArgumentsEvenIfAMockCallsAnother() {
-
-        final StringBuffer buffer = new StringBuffer();
-
-        final IMethods mock2 = createStrictMock(IMethods.class);
-        mock2.simpleMethod();
-        expectLastCall().andAnswer(new IAnswer<Object>() {
-            public Object answer() {
-                // empty, only needed to force deletion of arguments
-                return null;
-            }
-        }).times(2);
-
-        mock.simpleMethodWithArgument((String) notNull());
-        expectLastCall().andAnswer(new IAnswer<Object>() {
-            public Object answer() {
-                mock2.simpleMethod();
-                buffer.append((String) getCurrentArguments()[0]);
-                return null;
-            }
-        }).times(2);
-
-        replay(mock);
-        replay(mock2);
-
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        verify(mock);
-        verify(mock2);
-
-        assertEquals("12", buffer.toString());
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.IAnswer;
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class CallbackAndArgumentsTest {
+
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = createStrictMock(IMethods.class);
+    }
+
+    @Test
+    public void callbackGetsArguments() {
+
+        final StringBuilder buffer = new StringBuilder();
+
+        mock.simpleMethodWithArgument((String) notNull());
+        expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() {
+                buffer.append((String) getCurrentArguments()[0]);
+                return null;
+            }
+        }).times(2);
+
+        replay(mock);
+
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        verify(mock);
+
+        assertEquals("12", buffer.toString());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void currentArgumentsFailsOutsideCallbacks() {
+        getCurrentArguments();
+    }
+
+    @Test
+    public void callbackGetsArgumentsEvenIfAMockCallsAnother() {
+
+        final StringBuilder buffer = new StringBuilder();
+
+        final IMethods mock2 = createStrictMock(IMethods.class);
+        mock2.simpleMethod();
+        expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() {
+                // empty, only needed to force deletion of arguments
+                return null;
+            }
+        }).times(2);
+
+        mock.simpleMethodWithArgument((String) notNull());
+        expectLastCall().andAnswer(new IAnswer<Object>() {
+            public Object answer() {
+                mock2.simpleMethod();
+                buffer.append((String) getCurrentArguments()[0]);
+                return null;
+            }
+        }).times(2);
+
+        replay(mock);
+        replay(mock2);
+
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        verify(mock);
+        verify(mock2);
+
+        assertEquals("12", buffer.toString());
+    }
+}
diff --git a/tests/org/easymock/tests2/CallbackTest.java b/tests/org/easymock/tests2/CallbackTest.java
index 62c517b..3cc5c36 100644
--- a/tests/org/easymock/tests2/CallbackTest.java
+++ b/tests/org/easymock/tests2/CallbackTest.java
@@ -1,87 +1,101 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.IAnswer;
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class CallbackTest {
-
-    private IMethods mock;
-
-    private static class Callback<T> implements IAnswer<T> {
-        private int callCount;
-
-        private T result;
-
-        public Callback(T result) {
-            this.result = result;
-        }
-
-        public void run() {
-        }
-
-        public int getCallCount() {
-            return callCount;
-        }
-
-        public T answer() throws Throwable {
-            callCount++;
-            return result;
-        }
-    }
-
-    @Before
-    public void setUp() {
-        mock = createStrictMock(IMethods.class);
-    }
-
-    @Test
-    public void callback() {
-        Callback<String> c1 = new Callback<String>("1");
-        Callback<Object> c2 = new Callback<Object>(null);
-        Callback<Object> c3 = new Callback<Object>(null);
-
-        expect(mock.oneArg("2")).andAnswer(c1).times(2);
-        mock.simpleMethodWithArgument("One");
-        expectLastCall().andAnswer(c2);
-        mock.simpleMethodWithArgument("Two");
-        expectLastCall().andAnswer(c3).times(2);
-
-        replay(mock);
-
-        mock.oneArg("2");
-        mock.oneArg("2");
-        try {
-            mock.oneArg("2");
-        } catch (AssertionError ignored) {
-        }
-        try {
-            mock.simpleMethodWithArgument("Two");
-        } catch (AssertionError ignored) {
-        }
-        mock.simpleMethodWithArgument("One");
-        try {
-            mock.simpleMethodWithArgument("One");
-        } catch (AssertionError ignored) {
-        }
-        mock.simpleMethodWithArgument("Two");
-        mock.simpleMethodWithArgument("Two");
-        try {
-            mock.simpleMethodWithArgument("Two");
-        } catch (AssertionError ignored) {
-        }
-        verify(mock);
-
-        assertEquals(2, c1.getCallCount());
-        assertEquals(1, c2.getCallCount());
-        assertEquals(2, c3.getCallCount());
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.IAnswer;
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class CallbackTest {
+
+    private IMethods mock;
+
+    private static class Callback<T> implements IAnswer<T> {
+        private int callCount;
+
+        private final T result;
+
+        public Callback(final T result) {
+            this.result = result;
+        }
+
+        public void run() {
+        }
+
+        public int getCallCount() {
+            return callCount;
+        }
+
+        public T answer() throws Throwable {
+            callCount++;
+            return result;
+        }
+    }
+
+    @Before
+    public void setUp() {
+        mock = createStrictMock(IMethods.class);
+    }
+
+    @Test
+    public void callback() {
+        final Callback<String> c1 = new Callback<String>("1");
+        final Callback<Object> c2 = new Callback<Object>(null);
+        final Callback<Object> c3 = new Callback<Object>(null);
+
+        expect(mock.oneArg("2")).andAnswer(c1).times(2);
+        mock.simpleMethodWithArgument("One");
+        expectLastCall().andAnswer(c2);
+        mock.simpleMethodWithArgument("Two");
+        expectLastCall().andAnswer(c3).times(2);
+
+        replay(mock);
+
+        mock.oneArg("2");
+        mock.oneArg("2");
+        try {
+            mock.oneArg("2");
+        } catch (final AssertionError ignored) {
+        }
+        try {
+            mock.simpleMethodWithArgument("Two");
+        } catch (final AssertionError ignored) {
+        }
+        mock.simpleMethodWithArgument("One");
+        try {
+            mock.simpleMethodWithArgument("One");
+        } catch (final AssertionError ignored) {
+        }
+        mock.simpleMethodWithArgument("Two");
+        mock.simpleMethodWithArgument("Two");
+        try {
+            mock.simpleMethodWithArgument("Two");
+        } catch (final AssertionError ignored) {
+        }
+        verify(mock);
+
+        assertEquals(2, c1.getCallCount());
+        assertEquals(1, c2.getCallCount());
+        assertEquals(2, c3.getCallCount());
+    }
+}
diff --git a/tests/org/easymock/tests2/CaptureTest.java b/tests/org/easymock/tests2/CaptureTest.java
index 04bab19..77ad82e 100644
--- a/tests/org/easymock/tests2/CaptureTest.java
+++ b/tests/org/easymock/tests2/CaptureTest.java
@@ -1,158 +1,348 @@
-/*
- * Copyright (c) 2003-2008 OFFIS, Henri Tremblay. 
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.Capture;
-import org.easymock.tests.IMethods;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class CaptureTest {
-
-    public static class A {
-        public String foo(IMethods methods) {
-            return methods.oneArg(2);
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-    }
-
-    @After
-    public void tearDown() throws Exception {
-    }
-
-    // capture in thread
-    // after replay issue?
-
-    @Test
-    public void testCaptureRightOne() {
-        Capture<String> captured = new Capture<String>();
-        IMethods mock = createMock(IMethods.class);
-
-        expect(mock.oneArg(and(eq("test"), capture(captured)))).andReturn(
-                "answer1");
-        expect(mock.oneArg("a")).andReturn("answer2");
-
-        replay(mock);
-
-        assertEquals("answer2", mock.oneArg("a"));
-        assertFalse(captured.hasCaptured());
-
-        assertEquals("answer1", mock.oneArg("test"));
-        assertEquals("test", captured.getValue());
-
-        verify(mock);
-    }
-
-    @Test
-    public void testPrimitiveVsObject() {
-        Capture<Integer> capture = new Capture<Integer>();
-        IMethods mock = createMock(IMethods.class);
-
-        expect(mock.oneArg(capture(capture))).andReturn("answer");
-        expect(mock.oneArg((Integer) capture(capture))).andReturn("answer");
-
-        replay(mock);
-
-        assertEquals("answer", mock.oneArg(2));
-        assertEquals(2, capture.getValue().intValue());
-
-        assertEquals("answer", mock.oneArg(Integer.valueOf(3)));
-        assertEquals(3, capture.getValue().intValue());
-
-        verify(mock);
-    }
-
-    @Test
-    public void testAnd() {
-        Capture<String> captured = new Capture<String>();
-        IMethods mock = createMock(IMethods.class);
-
-        expect(mock.oneArg(and(capture(captured), eq("test")))).andReturn(
-                "answer");
-
-        replay(mock);
-
-        assertEquals("answer", mock.oneArg("test"));
-        assertEquals("test", captured.getValue());
-
-        verify(mock);
-    }
-    
-    @Test
-    public void testPrimitive() {
-        Capture<Integer> captureI = new Capture<Integer>();
-        Capture<Long> captureL = new Capture<Long>();
-        Capture<Float> captureF = new Capture<Float>();
-        Capture<Double> captureD = new Capture<Double>();
-        Capture<Byte> captureB = new Capture<Byte>();
-        Capture<Character> captureC = new Capture<Character>();
-
-        IMethods mock = createMock(IMethods.class);
-
-        expect(mock.oneArg(capture(captureI))).andReturn("answerI");
-        expect(mock.oneArg(capture(captureL))).andReturn("answerL");
-        expect(mock.oneArg(capture(captureF))).andReturn("answerF");
-        expect(mock.oneArg(capture(captureD))).andReturn("answerD");
-        expect(mock.oneArg(capture(captureB))).andReturn("answerB");
-        expect(mock.oneArg(capture(captureC))).andReturn("answerC");
-
-        replay(mock);
-
-        assertEquals("answerI", mock.oneArg(1));
-        assertEquals("answerL", mock.oneArg(2l));
-        assertEquals("answerF", mock.oneArg(3.0f));
-        assertEquals("answerD", mock.oneArg(4.0));
-        assertEquals("answerB", mock.oneArg((byte) 5));
-        assertEquals("answerC", mock.oneArg((char) 6));
-
-        assertEquals(1, captureI.getValue().intValue());
-        assertEquals(2l, captureL.getValue().longValue());
-        assertEquals(3.0f, captureF.getValue().floatValue(), 0.0);
-        assertEquals(4.0, captureD.getValue().doubleValue(), 0.0);
-        assertEquals((byte) 5, captureB.getValue().byteValue());
-        assertEquals((char) 6, captureC.getValue().charValue());
-        
-        verify(mock);
-    }
-    
-    @Test
-    public void testCapture() {
-        Capture<String> capture = new Capture<String>();
-        assertFalse(capture.hasCaptured());
-        try {
-            capture.getValue();
-            fail("Should not be allowed");
-        }
-        catch(AssertionError e) {
-            assertEquals("Nothing captured yet", e.getMessage());
-        }
-        assertEquals("Nothing captured yet", capture.toString());
-        capture.setValue("s");
-        assertTrue(capture.hasCaptured());
-        assertEquals("s", capture.getValue());
-        assertEquals("s", capture.toString());
-        capture.reset();
-        assertFalse(capture.hasCaptured());
-        try {
-            capture.getValue();
-            fail("Should not be allowed");
-        }
-        catch(AssertionError e) {
-            assertEquals("Nothing captured yet", e.getMessage());
-        }
-        
-        capture.setValue(null);
-        assertTrue(capture.hasCaptured());
-        assertNull(capture.getValue());
-        assertNull(capture.toString());
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.easymock.tests.IMethods;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class CaptureTest {
+
+    public static class A {
+        public String foo(final IMethods methods) {
+            return methods.oneArg(2);
+        }
+    }
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    private Capture<Integer> testCaptureType(final CaptureType type) {
+        final IMethods mock = createMock(IMethods.class);
+        final Capture<Integer> captured = new Capture<Integer>(type);
+
+        expect(mock.oneArg(captureInt(captured))).andReturn("1");
+        expect(mock.oneArg(anyInt())).andReturn("1");
+        expect(mock.oneArg(captureInt(captured))).andReturn("2").times(2);
+        mock.twoArgumentMethod(captureInt(captured), eq(5));
+        mock.twoArgumentMethod(captureInt(captured), captureInt(captured));
+
+        replay(mock);
+
+        mock.oneArg(0);
+        mock.oneArg(1);
+        mock.oneArg(2);
+        mock.oneArg(3);
+        mock.twoArgumentMethod(4, 5);
+        mock.twoArgumentMethod(6, 7);
+
+        verify(mock);
+
+        return captured;
+    }
+
+    @Test
+    public void testCaptureFirst() {
+        final Capture<Integer> captured = testCaptureType(CaptureType.FIRST);
+        assertEquals(0, (int) captured.getValue());
+    }
+
+    @Test
+    public void testCaptureLast() {
+        final Capture<Integer> captured = testCaptureType(CaptureType.LAST);
+        assertEquals(7, (int) captured.getValue());
+    }
+
+    @Test
+    public void testCaptureAll() {
+        final Capture<Integer> captured = testCaptureType(CaptureType.ALL);
+        assertEquals(Arrays.asList(0, 2, 3, 4, 6, 7), captured.getValues());
+    }
+
+    @Test
+    public void testCaptureNone() {
+        final Capture<Integer> captured = testCaptureType(CaptureType.NONE);
+        assertFalse(captured.hasCaptured());
+    }
+
+    // capture in thread
+    // after replay issue?
+
+    @Test
+    public void testCaptureRightOne() {
+        final Capture<String> captured = new Capture<String>();
+        final IMethods mock = createMock(IMethods.class);
+
+        expect(mock.oneArg(and(eq("test"), capture(captured)))).andReturn("answer1");
+        expect(mock.oneArg("a")).andReturn("answer2");
+
+        replay(mock);
+
+        assertEquals("answer2", mock.oneArg("a"));
+        assertFalse(captured.hasCaptured());
+
+        assertEquals("answer1", mock.oneArg("test"));
+        assertEquals("test", captured.getValue());
+
+        verify(mock);
+    }
+
+    @Test
+    public void testPrimitiveVsObject() {
+        final Capture<Integer> capture = new Capture<Integer>();
+        final IMethods mock = createMock(IMethods.class);
+
+        expect(mock.oneArg(captureInt(capture))).andReturn("answer");
+        expect(mock.oneArg(capture(capture))).andReturn("answer");
+
+        replay(mock);
+
+        assertEquals("answer", mock.oneArg(2));
+        assertEquals(2, capture.getValue().intValue());
+
+        assertEquals("answer", mock.oneArg(Integer.valueOf(3)));
+        assertEquals(3, capture.getValue().intValue());
+
+        verify(mock);
+    }
+
+    @Test
+    public void testAnd() {
+        final Capture<String> captured = new Capture<String>();
+        final IMethods mock = createMock(IMethods.class);
+
+        expect(mock.oneArg(and(capture(captured), eq("test")))).andReturn("answer");
+
+        replay(mock);
+
+        assertEquals("answer", mock.oneArg("test"));
+        assertEquals("test", captured.getValue());
+
+        verify(mock);
+    }
+
+    @Test
+    public void testPrimitive() {
+        final Capture<Integer> captureI = new Capture<Integer>();
+        final Capture<Long> captureL = new Capture<Long>();
+        final Capture<Float> captureF = new Capture<Float>();
+        final Capture<Double> captureD = new Capture<Double>();
+        final Capture<Byte> captureB = new Capture<Byte>();
+        final Capture<Character> captureC = new Capture<Character>();
+        final Capture<Boolean> captureBool = new Capture<Boolean>();
+
+        final IMethods mock = createMock(IMethods.class);
+
+        expect(mock.oneArg(captureInt(captureI))).andReturn("answerI");
+        expect(mock.oneArg(captureLong(captureL))).andReturn("answerL");
+        expect(mock.oneArg(captureFloat(captureF))).andReturn("answerF");
+        expect(mock.oneArg(captureDouble(captureD))).andReturn("answerD");
+        expect(mock.oneArg(captureByte(captureB))).andReturn("answerB");
+        expect(mock.oneArg(captureChar(captureC))).andReturn("answerC");
+        expect(mock.oneArg(captureBoolean(captureBool))).andReturn("answerZ");
+
+        replay(mock);
+
+        assertEquals("answerI", mock.oneArg(1));
+        assertEquals("answerL", mock.oneArg(2l));
+        assertEquals("answerF", mock.oneArg(3.0f));
+        assertEquals("answerD", mock.oneArg(4.0));
+        assertEquals("answerB", mock.oneArg((byte) 5));
+        assertEquals("answerC", mock.oneArg((char) 6));
+        assertEquals("answerZ", mock.oneArg(true));
+
+        assertEquals(1, captureI.getValue().intValue());
+        assertEquals(2l, captureL.getValue().longValue());
+        assertEquals(3.0f, captureF.getValue().floatValue(), 0.0);
+        assertEquals(4.0, captureD.getValue().doubleValue(), 0.0);
+        assertEquals((byte) 5, captureB.getValue().byteValue());
+        assertEquals((char) 6, captureC.getValue().charValue());
+        assertEquals(true, captureBool.getValue().booleanValue());
+
+        verify(mock);
+    }
+
+    @Test
+    public void testCapture() {
+        final Capture<String> capture = new Capture<String>();
+        assertFalse(capture.hasCaptured());
+        try {
+            capture.getValue();
+            fail("Should not be allowed");
+        } catch (final AssertionError e) {
+            assertEquals("Nothing captured yet", e.getMessage());
+        }
+        assertEquals("Nothing captured yet", capture.toString());
+        capture.setValue("s");
+        assertTrue(capture.hasCaptured());
+        assertEquals("s", capture.getValue());
+        assertEquals("s", capture.toString());
+        capture.reset();
+        assertFalse(capture.hasCaptured());
+        try {
+            capture.getValue();
+            fail();
+        } catch (final AssertionError e) {
+            assertEquals("Nothing captured yet", e.getMessage());
+        }
+
+        capture.setValue(null);
+        assertTrue(capture.hasCaptured());
+        assertNull(capture.getValue());
+        assertEquals("null", capture.toString());
+    }
+
+    @Test
+    public void testCaptureMultiple() {
+        final Capture<String> capture = new Capture<String>(CaptureType.ALL);
+        capture.setValue("a");
+        capture.setValue("b");
+        try {
+            capture.getValue();
+            fail();
+        } catch (final AssertionError e) {
+            assertEquals("More than one value captured: " + capture.getValues(), e.getMessage());
+        }
+        assertEquals(Arrays.asList("a", "b"), capture.getValues());
+    }
+
+    @Test
+    public void testCapture_2617107() {
+
+        final IMethods mock = createMock(IMethods.class);
+
+        final Capture<String> cap1 = new Capture<String>();
+        final Capture<String> cap2 = new Capture<String>();
+        final Capture<String> cap3 = new Capture<String>();
+        final Capture<String> cap4 = new Capture<String>();
+
+        mock.simpleMethodWithArgument(and(isA(String.class), capture(cap1)));
+        mock.simpleMethodWithArgument(and(isA(String.class), capture(cap2)));
+        mock.simpleMethodWithArgument(and(isA(String.class), capture(cap3)));
+        mock.simpleMethodWithArgument(and(isA(String.class), capture(cap4)));
+
+        replay(mock);
+
+        final String[] s = { "one", "two", "three", "four" };
+
+        for (final String element : s) {
+            mock.simpleMethodWithArgument(element);
+        }
+
+        assertEquals("one", cap1.getValue());
+        assertEquals("two", cap2.getValue());
+        assertEquals("three", cap3.getValue());
+        assertEquals("four", cap4.getValue());
+
+        verify(mock);
+    }
+
+    @Test
+    public void testCaptureNonStrictControl_2133741() {
+        testCaptureHelper(createMock(IMethods.class));
+    }
+
+    @Test
+    public void testCaptureStrictControl_2133741() {
+        testCaptureHelper(createStrictMock(IMethods.class));
+    }
+
+    protected void testCaptureHelper(final IMethods mock) {
+        final Capture<String> capture1 = new Capture<String>();
+        final Capture<String> capture2 = new Capture<String>();
+
+        mock.simpleMethodWithArgument(capture(capture1));
+        mock.simpleMethodWithArgument(capture(capture2));
+
+        replay(mock);
+        mock.simpleMethodWithArgument("a");
+        mock.simpleMethodWithArgument("b");
+        verify(mock);
+
+        assertTrue(capture1.hasCaptured());
+        assertTrue(capture2.hasCaptured());
+        assertFalse(capture1.getValue() == capture2.getValue());
+    }
+
+    @Test
+    public void testCapture1_2446744() {
+        final Capture<String> capture1 = new Capture<String>();
+        final Capture<String> capture2 = new Capture<String>();
+        final Capture<String> capture3 = new Capture<String>();
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg(capture(capture1))).andReturn("1").once();
+        expect(mock.oneArg(capture(capture2))).andReturn("2").once();
+        expect(mock.oneArg(capture(capture3))).andReturn("3").once();
+
+        replay(mock);
+
+        for (int i = 0; i < 3; i++) {
+            final String string = "Run" + (i + 1);
+            mock.oneArg(string);
+        }
+
+        assertEquals("Run3", capture3.getValue());
+        assertEquals("Run2", capture2.getValue());
+        assertEquals("Run1", capture1.getValue());
+    }
+
+    @Test
+    public void testCapture2_2446744() {
+        final Capture<String> capture = new Capture<String>(CaptureType.ALL);
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg(capture(capture))).andReturn("1").once();
+        expect(mock.oneArg(capture(capture))).andReturn("2").once();
+        expect(mock.oneArg(capture(capture))).andReturn("3").once();
+
+        replay(mock);
+
+        for (int i = 0; i < 3; i++) {
+            final String string = "Run" + (i + 1);
+            mock.oneArg(string);
+        }
+
+        assertEquals(Arrays.asList("Run1", "Run2", "Run3"), capture.getValues());
+    }
+
+    @Test
+    public void testCaptureFromStub() {
+        final Capture<String> capture = new Capture<String>(CaptureType.ALL);
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg(capture(capture))).andStubReturn("1");
+
+        replay(mock);
+
+        mock.oneArg("test");
+
+        assertEquals("test", capture.getValue());
+    }
+}
diff --git a/tests/org/easymock/tests2/ChildEquals.java b/tests/org/easymock/tests2/ChildEquals.java
new file mode 100644
index 0000000..bab1880
--- /dev/null
+++ b/tests/org/easymock/tests2/ChildEquals.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ChildEquals extends ParentEquals {
+    public String getString() {
+        return "x";
+    }
+}
diff --git a/tests/org/easymock/tests2/ClassExtensionHelperTest.java b/tests/org/easymock/tests2/ClassExtensionHelperTest.java
new file mode 100644
index 0000000..b40466c
--- /dev/null
+++ b/tests/org/easymock/tests2/ClassExtensionHelperTest.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import com.google.dexmaker.stock.ProxyBuilder;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.List;
+import net.sf.cglib.proxy.Enhancer;
+import net.sf.cglib.proxy.NoOp;
+import org.easymock.EasyMock;
+import static org.easymock.EasyMock.createMock;
+import org.easymock.internal.AndroidSupport;
+import static org.easymock.internal.MocksControl.getControl;
+import static org.easymock.internal.MocksControl.getMockedType;
+import org.easymock.internal.MocksControl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ClassExtensionHelperTest {
+
+    private static final InvocationHandler NOOP_INVOCATION_HANDLER = new InvocationHandler() {
+        public Object invoke(Object proxy, Method method, Object[] args) {
+            return null;
+        }
+    };
+
+    @Test
+    public void testGetControl_EasyMock() {
+        final List<?> mock = EasyMock.createMock(List.class);
+        assertNotNull(getControl(mock));
+    }
+
+    @Test
+    public void testGetControl_EasyMockClassExtension() {
+        final ArrayList<?> mock = EasyMock.createMock(ArrayList.class);
+        assertTrue(getControl(mock) instanceof MocksControl);
+    }
+
+    @Test
+    public void testGetControl_EnhancedButNotAMock() throws Exception {
+        final Object o;
+        if (AndroidSupport.isAndroid()) {
+            o = ProxyBuilder.forClass(ArrayList.class)
+                    .handler(NOOP_INVOCATION_HANDLER)
+                    .build();
+        } else {
+            o = Enhancer.create(ArrayList.class, NoOp.INSTANCE);
+        }
+        try {
+            getControl(o);
+            fail();
+        } catch (final IllegalArgumentException e) {
+            assertEquals("Not a mock: " + o.getClass().getName(), e.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetControl_ProxyButNotMock() {
+        final Object o = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { List.class },
+                new InvocationHandler() {
+                    public Object invoke(final Object proxy, final Method method, final Object[] args)
+                            throws Throwable {
+                        return null;
+                    }
+                });
+        try {
+            getControl(o);
+            fail();
+        } catch (final IllegalArgumentException e) {
+            assertEquals("Not a mock: " + o.getClass().getName(), e.getMessage());
+        }
+    }
+
+    @Test
+    public void testGetControl_NotAMock() {
+        try {
+            getControl("");
+            fail();
+        } catch (final IllegalArgumentException expected) {
+        }
+    }
+
+    @Test
+    public void testMockType_Class() {
+        final Object o = createMock(ArrayList.class);
+        final Class<?> c = getMockedType(o);
+        assertEquals(ArrayList.class, c);
+    }
+
+    @Test
+    public void testMockType_Interface() {
+        final Object o = createMock(List.class);
+        final Class<?> c = getMockedType(o);
+        assertEquals(List.class, c);
+    }
+}
diff --git a/tests/org/easymock/tests2/CompareToTest.java b/tests/org/easymock/tests2/CompareToTest.java
index b89e2b7..ba7f159 100644
--- a/tests/org/easymock/tests2/CompareToTest.java
+++ b/tests/org/easymock/tests2/CompareToTest.java
@@ -1,79 +1,93 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.junit.Assert.*;
-
-import java.math.BigDecimal;
-
-import org.easymock.internal.matchers.*;
-import org.junit.Test;
-
-public class CompareToTest {
-
-    @Test
-    public void testNotComparable() {
-        CompareTo<Long> cmpTo = new CompareTo<Long>(5L) {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected String getName() {
-                return null;
-            }
-
-            @Override
-            protected boolean matchResult(int result) {
-                fail("Shouldn't be called since the passed argument is not Comparable");
-                return true;
-            }
-            
-        };
-        
-        assertFalse(cmpTo.matches(new Object()));
-    }
-    @Test
-    public void testLessThan() {
-        test(new LessThan<String>("b"), true, false, false, "lt");
-    }
-
-    @Test
-    public void testGreateThan() {
-        test(new GreaterThan<String>("b"), false, true, false, "gt");
-    }
-
-    @Test
-    public void testLessOrEqual() {
-        test(new LessOrEqual<String>("b"), true, false, true, "leq");
-    }
-
-    @Test
-    public void testGreateOrEqual() {
-        test(new GreaterOrEqual<String>("b"), false, true, true, "geq");
-    }
-
-    @Test
-    public void testCompareEqual() {
-        test(new CompareEqual<String>("b"), false, false, true, "cmpEq");
-
-        // Make sure it works when equals provide a different result than
-        // compare
-        CompareEqual<BigDecimal> cmpEq = new CompareEqual<BigDecimal>(
-                new BigDecimal("5.00"));
-        assertTrue(cmpEq.matches(new BigDecimal("5")));
-    }
-
-    private void test(CompareTo<String> cmpTo, boolean lower, boolean higher,
-            boolean equals, String name) {
-
-        assertEquals(lower, cmpTo.matches("a"));
-        assertEquals(equals, cmpTo.matches("b"));
-        assertEquals(higher, cmpTo.matches("c"));
-
-        StringBuffer sb = new StringBuffer();
-        cmpTo.appendTo(sb);
-        assertEquals(name + "(b)", sb.toString());
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.junit.Assert.*;
+
+import java.math.BigDecimal;
+
+import org.easymock.internal.matchers.*;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class CompareToTest {
+
+    @Test
+    public void testNotComparable() {
+        final CompareTo<Long> cmpTo = new CompareTo<Long>(5L) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected String getName() {
+                return null;
+            }
+
+            @Override
+            protected boolean matchResult(final int result) {
+                fail("Shouldn't be called since the passed argument is not Comparable");
+                return true;
+            }
+
+        };
+
+        assertFalse(cmpTo.matches(new Object()));
+    }
+
+    @Test
+    public void testLessThan() {
+        test(new LessThan<String>("b"), true, false, false, "lt");
+    }
+
+    @Test
+    public void testGreateThan() {
+        test(new GreaterThan<String>("b"), false, true, false, "gt");
+    }
+
+    @Test
+    public void testLessOrEqual() {
+        test(new LessOrEqual<String>("b"), true, false, true, "leq");
+    }
+
+    @Test
+    public void testGreateOrEqual() {
+        test(new GreaterOrEqual<String>("b"), false, true, true, "geq");
+    }
+
+    @Test
+    public void testCompareEqual() {
+        test(new CompareEqual<String>("b"), false, false, true, "cmpEq");
+
+        // Make sure it works when equals provide a different result than
+        // compare
+        final CompareEqual<BigDecimal> cmpEq = new CompareEqual<BigDecimal>(new BigDecimal("5.00"));
+        assertTrue(cmpEq.matches(new BigDecimal("5")));
+    }
+
+    private void test(final CompareTo<String> cmpTo, final boolean lower, final boolean higher,
+            final boolean equals, final String name) {
+
+        assertEquals(lower, cmpTo.matches("a"));
+        assertEquals(equals, cmpTo.matches("b"));
+        assertEquals(higher, cmpTo.matches("c"));
+
+        final StringBuffer sb = new StringBuffer();
+        cmpTo.appendTo(sb);
+        assertEquals(name + "(b)", sb.toString());
+    }
+}
diff --git a/tests/org/easymock/tests2/ConstraintsToStringTest.java b/tests/org/easymock/tests2/ConstraintsToStringTest.java
index 87aa9ef..1147b8f 100644
--- a/tests/org/easymock/tests2/ConstraintsToStringTest.java
+++ b/tests/org/easymock/tests2/ConstraintsToStringTest.java
@@ -1,147 +1,179 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.easymock.IArgumentMatcher;
-import org.easymock.internal.matchers.*;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ConstraintsToStringTest {
-    private StringBuffer buffer;
-
-    @Before
-    public void setup() {
-        buffer = new StringBuffer();
-    }
-
-    @Test
-    public void sameToStringWithString() {
-        new Same("X").appendTo(buffer);
-        assertEquals("same(\"X\")", buffer.toString());
-
-    }
-
-    @Test
-    public void nullToString() {
-        Null.NULL.appendTo(buffer);
-        assertEquals("isNull()", buffer.toString());
-    }
-
-    @Test
-    public void notNullToString() {
-        NotNull.NOT_NULL.appendTo(buffer);
-        assertEquals("notNull()", buffer.toString());
-    }
-
-    @Test
-    public void anyToString() {
-        Any.ANY.appendTo(buffer);
-        assertEquals("<any>", buffer.toString());
-    }
-
-    @Test
-    public void sameToStringWithChar() {
-        new Same('x').appendTo(buffer);
-        assertEquals("same('x')", buffer.toString());
-    }
-
-    @Test
-    public void sameToStringWithObject() {
-        Object o = new Object() {
-            @Override
-            public String toString() {
-                return "X";
-            }
-        };
-        new Same(o).appendTo(buffer);
-        assertEquals("same(X)", buffer.toString());
-    }
-
-    @Test
-    public void equalsToStringWithString() {
-        new Equals("X").appendTo(buffer);
-        assertEquals("\"X\"", buffer.toString());
-
-    }
-
-    @Test
-    public void equalsToStringWithChar() {
-        new Equals('x').appendTo(buffer);
-        assertEquals("'x'", buffer.toString());
-    }
-
-    @Test
-    public void equalsToStringWithObject() {
-        Object o = new Object() {
-            @Override
-            public String toString() {
-                return "X";
-            }
-        };
-        new Equals(o).appendTo(buffer);
-        assertEquals("X", buffer.toString());
-    }
-
-    @Test
-    public void orToString() {
-        List<IArgumentMatcher> matchers = new ArrayList<IArgumentMatcher>();
-        matchers.add(new Equals(1));
-        matchers.add(new Equals(2));
-        new Or(matchers).appendTo(buffer);
-        assertEquals("or(1, 2)", buffer.toString());
-    }
-
-    @Test
-    public void notToString() {
-        new Not(new Equals(1)).appendTo(buffer);
-        assertEquals("not(1)", buffer.toString());
-    }
-
-    @Test
-    public void andToString() {
-        List<IArgumentMatcher> matchers = new ArrayList<IArgumentMatcher>();
-        matchers.add(new Equals(1));
-        matchers.add(new Equals(2));
-        new And(matchers).appendTo(buffer);
-        assertEquals("and(1, 2)", buffer.toString());
-    }
-
-    @Test
-    public void startsWithToString() {
-        new StartsWith("AB").appendTo(buffer);
-        assertEquals("startsWith(\"AB\")", buffer.toString());
-    }
-
-    @Test
-    public void endsWithToString() {
-        new EndsWith("AB").appendTo(buffer);
-        assertEquals("endsWith(\"AB\")", buffer.toString());
-    }
-
-    @Test
-    public void containsToString() {
-        new Contains("AB").appendTo(buffer);
-        assertEquals("contains(\"AB\")", buffer.toString());
-    }
-
-    @Test
-    public void findToString() {
-        new Find("\\s+").appendTo(buffer);
-        assertEquals("find(\"\\\\s+\")", buffer.toString());
-    }
-
-    @Test
-    public void matchesToString() {
-        new Matches("\\s+").appendTo(buffer);
-        assertEquals("matches(\"\\\\s+\")", buffer.toString());
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.IArgumentMatcher;
+import org.easymock.internal.matchers.*;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class ConstraintsToStringTest {
+    private StringBuffer buffer;
+
+    @Before
+    public void setup() {
+        buffer = new StringBuffer();
+    }
+
+    @Test
+    public void sameToStringWithString() {
+        new Same("X").appendTo(buffer);
+        assertEquals("same(\"X\")", buffer.toString());
+
+    }
+
+    @Test
+    public void nullToString() {
+        Null.NULL.appendTo(buffer);
+        assertEquals("isNull()", buffer.toString());
+    }
+
+    @Test
+    public void notNullToString() {
+        NotNull.NOT_NULL.appendTo(buffer);
+        assertEquals("notNull()", buffer.toString());
+    }
+
+    @Test
+    public void anyToString() {
+        Any.ANY.appendTo(buffer);
+        assertEquals("<any>", buffer.toString());
+    }
+
+    @Test
+    public void sameToStringWithChar() {
+        new Same('x').appendTo(buffer);
+        assertEquals("same('x')", buffer.toString());
+    }
+
+    @Test
+    public void sameToStringWithObject() {
+        final Object o = new Object() {
+            @Override
+            public String toString() {
+                return "X";
+            }
+        };
+        new Same(o).appendTo(buffer);
+        assertEquals("same(X)", buffer.toString());
+    }
+
+    @Test
+    public void equalsToStringWithString() {
+        new Equals("X").appendTo(buffer);
+        assertEquals("\"X\"", buffer.toString());
+
+    }
+
+    @Test
+    public void equalsToStringWithChar() {
+        new Equals('x').appendTo(buffer);
+        assertEquals("'x'", buffer.toString());
+    }
+
+    @Test
+    public void equalsToStringWithObject() {
+        final Object o = new Object() {
+            @Override
+            public String toString() {
+                return "X";
+            }
+        };
+        new Equals(o).appendTo(buffer);
+        assertEquals("X", buffer.toString());
+    }
+
+    @Test
+    public void equalsToStringWithArray() {
+        final String[] s = new String[] { "a", "b", null, "c" };
+        new Equals(s).appendTo(buffer);
+        assertEquals("[\"a\", \"b\", null, \"c\"]", buffer.toString());
+    }
+
+    @Test
+    public void orToString() {
+        final List<IArgumentMatcher> matchers = new ArrayList<IArgumentMatcher>();
+        matchers.add(new Equals(1));
+        matchers.add(new Equals(2));
+        new Or(matchers).appendTo(buffer);
+        assertEquals("or(1, 2)", buffer.toString());
+    }
+
+    @Test
+    public void notToString() {
+        new Not(new Equals(1)).appendTo(buffer);
+        assertEquals("not(1)", buffer.toString());
+    }
+
+    @Test
+    public void andToString() {
+        final List<IArgumentMatcher> matchers = new ArrayList<IArgumentMatcher>();
+        matchers.add(new Equals(1));
+        matchers.add(new Equals(2));
+        new And(matchers).appendTo(buffer);
+        assertEquals("and(1, 2)", buffer.toString());
+    }
+
+    @Test
+    public void startsWithToString() {
+        new StartsWith("AB").appendTo(buffer);
+        assertEquals("startsWith(\"AB\")", buffer.toString());
+    }
+
+    @Test
+    public void endsWithToString() {
+        new EndsWith("AB").appendTo(buffer);
+        assertEquals("endsWith(\"AB\")", buffer.toString());
+    }
+
+    @Test
+    public void containsToString() {
+        new Contains("AB").appendTo(buffer);
+        assertEquals("contains(\"AB\")", buffer.toString());
+    }
+
+    @Test
+    public void findToString() {
+        new Find("\\s+").appendTo(buffer);
+        assertEquals("find(\"\\\\s+\")", buffer.toString());
+    }
+
+    @Test
+    public void matchesToString() {
+        new Matches("\\s+").appendTo(buffer);
+        assertEquals("matches(\"\\\\s+\")", buffer.toString());
+    }
+
+    @Test
+    public void equalsWithDeltaToString() {
+        new EqualsWithDelta(2.1d, 0.2d).appendTo(buffer);
+        assertEquals("eq(2.1, 0.2)", buffer.toString());
+    }
+
+    @Test
+    public void arrayEqualsToString() {
+        new ArrayEquals(new Object[] { 1, "a", null }).appendTo(buffer);
+        assertEquals("[1, \"a\", null]", buffer.toString());
+    }
+}
diff --git a/tests/org/easymock/tests2/ConstructorArgsTest.java b/tests/org/easymock/tests2/ConstructorArgsTest.java
new file mode 100644
index 0000000..fbba74d
--- /dev/null
+++ b/tests/org/easymock/tests2/ConstructorArgsTest.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.junit.Assert.*;
+
+import org.easymock.ConstructorArgs;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ConstructorArgsTest {
+
+    public final Class<?> TYPE = null;
+
+    public static class A {
+
+        private static final Class<?> TYPE = null;
+
+        public A(final String s, final int i) {
+        }
+    }
+
+    @Test
+    public void testConstructorArgs() {
+        final ConstructorArgs args = new ConstructorArgs(A.class.getConstructors()[0], "a", 4);
+        checkArgs(args);
+    }
+
+    private void checkArgs(final ConstructorArgs args) {
+        assertEquals(2, args.getInitArgs().length);
+        assertEquals("a", args.getInitArgs()[0]);
+        assertEquals(4, args.getInitArgs()[1]);
+
+        assertEquals(A.class.getConstructors()[0], args.getConstructor());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_WrongArgument() {
+        new ConstructorArgs(A.class.getConstructors()[0], "a", "b");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_NullPrimitive() {
+        new ConstructorArgs(A.class.getConstructors()[0], "a", null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_PrimitiveForObject() {
+        new ConstructorArgs(A.class.getConstructors()[0], 1, 2);
+    }
+
+    @Test
+    public void testConstructorArgs_NullObject() {
+        new ConstructorArgs(A.class.getConstructors()[0], null, 2);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_WrongPrimitive() {
+        new ConstructorArgs(A.class.getConstructors()[0], "a", 2.0f);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_WrongNumberOfArgs() {
+        new ConstructorArgs(A.class.getConstructors()[0], "a");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_TypeExistsButPrivate() {
+        new ConstructorArgs(A.class.getConstructors()[0], "a", new A(null, 1));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorArgs_TypeExistsButNotStatic() {
+        new ConstructorArgs(A.class.getConstructors()[0], "a", new ConstructorArgsTest());
+    }
+}
diff --git a/tests/org/easymock/tests2/DelegateToTest.java b/tests/org/easymock/tests2/DelegateToTest.java
new file mode 100644
index 0000000..4afa7ad
--- /dev/null
+++ b/tests/org/easymock/tests2/DelegateToTest.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class DelegateToTest {
+
+    public static interface IMyInterface {
+        int getInt(int k);
+    }
+
+    @Test
+    public void testDelegate() {
+        final IMyInterface mock = createMock(IMyInterface.class);
+        final IMyInterface delegateTo = new IMyInterface() {
+            private int i = 0;
+
+            public int getInt(final int k) {
+                return i += k;
+            }
+        };
+
+        expect(mock.getInt(10)).andDelegateTo(delegateTo);
+        expect(mock.getInt(5)).andDelegateTo(delegateTo).andDelegateTo(delegateTo).times(2);
+
+        replay(mock);
+
+        assertEquals(10, mock.getInt(10));
+        assertEquals(15, mock.getInt(5));
+        assertEquals(20, mock.getInt(5));
+        assertEquals(25, mock.getInt(5));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testStubDelegate() {
+        final IMyInterface mock = createMock(IMyInterface.class);
+        final IMyInterface delegateTo = new IMyInterface() {
+            private int i = 0;
+
+            public int getInt(final int k) {
+                return ++i;
+            }
+        };
+        expect(mock.getInt(5)).andReturn(3).andStubDelegateTo(delegateTo);
+        expect(mock.getInt(20)).andStubDelegateTo(delegateTo);
+
+        replay(mock);
+
+        assertEquals(3, mock.getInt(5));
+        assertEquals(1, mock.getInt(5));
+        assertEquals(2, mock.getInt(5));
+        assertEquals(3, mock.getInt(20));
+        assertEquals(4, mock.getInt(20));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testReturnException() {
+        final IMyInterface m = createMock(IMyInterface.class);
+        final IMyInterface delegateTo = new IMyInterface() {
+            public int getInt(final int k) {
+                throw new ArithmeticException("Not good!");
+            }
+        };
+        expect(m.getInt(5)).andDelegateTo(delegateTo);
+
+        replay(m);
+
+        try {
+            m.getInt(5);
+            fail();
+        } catch (final ArithmeticException e) {
+            assertEquals("Not good!", e.getMessage());
+        }
+
+        verify(m);
+    }
+
+    @Test
+    public void testWrongClass() {
+        final IMyInterface m = createMock(IMyInterface.class);
+        expect(m.getInt(0)).andDelegateTo("allo");
+        replay(m);
+        try {
+            m.getInt(0);
+            fail("Should throw an exception");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(
+                    "Delegation to object [allo] is not implementing the mocked method [public abstract int org.easymock.tests2.DelegateToTest$IMyInterface.getInt(int)]",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void nullDelegationNotAllowed() {
+        final IMyInterface mock = createMock(IMyInterface.class);
+        try {
+            expect(mock.getInt(1)).andDelegateTo(null);
+            fail();
+        } catch (final NullPointerException expected) {
+            assertEquals("delegated to object must not be null", expected.getMessage());
+        }
+    }
+
+    @Test
+    public void nullStubDelegationNotAllowed() {
+        final IMyInterface mock = createMock(IMyInterface.class);
+        try {
+            expect(mock.getInt(1)).andStubDelegateTo(null);
+            fail();
+        } catch (final NullPointerException expected) {
+            assertEquals("delegated to object must not be null", expected.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests2/DependencyTest.java b/tests/org/easymock/tests2/DependencyTest.java
new file mode 100644
index 0000000..41f9621
--- /dev/null
+++ b/tests/org/easymock/tests2/DependencyTest.java
@@ -0,0 +1,74 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.EasyMockSupport;
+import org.easymock.tests.IMethods;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class DependencyTest {
+
+    private final EasyMockSupport support = new EasyMockSupport();
+
+    @Rule
+    public FilteringRule rule = new FilteringRule("net.sf.cglib", "org.objenesis");
+
+    @Test
+    public void testInterfaceMocking() {
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.booleanReturningMethod(1)).andReturn(true);
+        replay(mock);
+        assertTrue(mock.booleanReturningMethod(1));
+        verify(mock);
+    }
+
+    @Test
+    public void testClassMocking() {
+        try {
+            final DependencyTest mock = createMock(DependencyTest.class);
+            fail("Should throw an exception due to a NoClassDefFoundError");
+        } catch (final RuntimeException e) {
+            assertEquals("Class mocking requires to have cglib and objenesis librairies in the classpath", e
+                    .getMessage());
+            assertTrue(e.getCause() instanceof NoClassDefFoundError);
+        }
+    }
+
+    @Test
+    public void testInterfaceMockingSupport() {
+        final IMethods mock = support.createMock(IMethods.class);
+        expect(mock.booleanReturningMethod(1)).andReturn(true);
+        support.replayAll();
+        assertTrue(mock.booleanReturningMethod(1));
+        support.verifyAll();
+    }
+
+    @Test
+    public void testClassMockingSupport() {
+        try {
+            final DependencyTest mock = support.createMock(DependencyTest.class);
+            fail("Should throw an exception due to a NoClassDefFoundError");
+        } catch (final RuntimeException e) {
+            assertEquals("Class mocking requires to have cglib and objenesis librairies in the classpath", e
+                    .getMessage());
+            assertTrue(e.getCause() instanceof NoClassDefFoundError);
+        }
+    }
+}
diff --git a/tests/org/easymock/tests2/EasyMockClassExtensionTest.java b/tests/org/easymock/tests2/EasyMockClassExtensionTest.java
new file mode 100644
index 0000000..af6b9ca
--- /dev/null
+++ b/tests/org/easymock/tests2/EasyMockClassExtensionTest.java
@@ -0,0 +1,384 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.easymock.ConstructorArgs;
+import org.easymock.EasyMock;
+import org.easymock.IMockBuilder;
+import org.easymock.internal.EasyMockProperties;
+import org.easymock.tests2.MocksControlTest.A;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class EasyMockClassExtensionTest {
+
+    private static class ParamEntry {
+        Class<?>[] types;
+
+        Object[] values;
+
+        ParamEntry(final Class<?>[] types, final Object[] values) {
+            this.types = types;
+            this.values = values;
+        }
+
+        boolean isNamed() {
+            return types[0] == String.class;
+        }
+
+        boolean isConstructorCalled() {
+            return Arrays.asList(types).contains(ConstructorArgs.class);
+        }
+
+        A getMock(final String methodName) throws Exception {
+            final Method m = EasyMock.class.getMethod(methodName, types);
+            return (A) m.invoke(null, values);
+        }
+
+        public void test(final A mock) {
+            if (isNamed()) {
+                testNamed(mock);
+            }
+            if (isConstructorCalled()) {
+                testPartial_ConstructorCalled(mock);
+            } else {
+                testPartial_NoConstructorCalled(mock);
+            }
+        }
+    }
+
+    /** Types of all method flavors */
+    /** Types of all method flavors */
+    private static final Class<?>[][] PARAMETER_TYPES = new Class<?>[][] { new Class[] { Class.class }, //
+            new Class[] { String.class, Class.class }, //
+            new Class[] { Class.class, Method[].class }, //
+            new Class[] { String.class, Class.class, Method[].class }, //
+            new Class[] { Class.class, ConstructorArgs.class, Method[].class }, //
+            new Class[] { String.class, Class.class, ConstructorArgs.class, Method[].class } //
+    };
+
+    /** Values to pass to each method call */
+    private static final Object[][] PARAMETER_VALUES;
+
+    /** All 6 flavors of method calls */
+    private static final ParamEntry[] PARAMETERS = new ParamEntry[PARAMETER_TYPES.length];
+
+    static {
+
+        Method[] methods;
+        try {
+            methods = new Method[] { A.class.getMethod("add", Integer.TYPE), A.class.getMethod("toString") };
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+        ConstructorArgs args;
+        try {
+            args = new ConstructorArgs(A.class.getConstructor(Integer.TYPE), 3);
+        } catch (final SecurityException e) {
+            throw new RuntimeException(e);
+        } catch (final NoSuchMethodException e) {
+            throw new RuntimeException(e);
+        }
+
+        PARAMETER_VALUES = new Object[][] { new Object[] { A.class }, //
+                new Object[] { "myMock", A.class }, //
+                new Object[] { A.class, methods }, //
+                new Object[] { "myMock", A.class, methods }, //
+                new Object[] { A.class, args, methods }, //
+                new Object[] { "myMock", A.class, args, methods } //
+        };
+
+        for (int i = 0; i < PARAMETERS.length; i++) {
+            PARAMETERS[i] = new ParamEntry(PARAMETER_TYPES[i], PARAMETER_VALUES[i]);
+        }
+    }
+
+    @Test
+    public void testDisablingClassMocking() {
+        EasyMockProperties.getInstance().setProperty(DISABLE_CLASS_MOCKING, Boolean.TRUE.toString());
+        try {
+            final ArrayList<?> list = createMock(ArrayList.class);
+            fail("Class mocking should be disabled");
+        } catch (final IllegalArgumentException e) {
+            assertEquals("Class mocking is currently disabled. Change " + EasyMock.DISABLE_CLASS_MOCKING
+                    + " to true do modify this behavior", e.getMessage());
+        } finally {
+            EasyMockProperties.getInstance().setProperty(DISABLE_CLASS_MOCKING, null);
+        }
+    }
+
+    @Test
+    public void testClassMocking() {
+        final ArrayList<?> list = createMock(ArrayList.class);
+        testList(list);
+    }
+
+    @Test
+    public void testInterfaceMocking() {
+        final List<?> list = createMock(List.class);
+        testList(list);
+    }
+
+    private void testList(final List<?> list) {
+        expect(list.size()).andReturn(3);
+        replay(list);
+        assertEquals(3, list.size());
+        verify(list);
+    }
+
+    @Test
+    public void testResetReplay() {
+        final ArrayList<?> list = createStrictMock(ArrayList.class);
+        expect(list.size()).andReturn(3);
+        reset(list);
+        expect(list.size()).andReturn(1);
+        replay(list);
+        assertEquals(1, list.size());
+        verify(list);
+    }
+
+    @Test
+    public void testResetTo() {
+        final ArrayList<?> list = createMock(ArrayList.class);
+        // Just to make sure the all can be called on a mock
+        resetToNice(list);
+        resetToStrict(list);
+        resetToDefault(list);
+    }
+
+    @Test
+    public void testMakeThreadSafe() {
+        final ArrayList<?> list = createMock(ArrayList.class);
+        // Just to make sure the all can be called on a mock
+        makeThreadSafe(list, true);
+    }
+
+    @Test
+    public void testVarargs() {
+        final ArrayList<?> list2 = createStrictMock(ArrayList.class);
+        final ArrayList<?> list1 = createStrictMock(ArrayList.class);
+
+        expect(list1.size()).andReturn(1);
+        expect(list2.size()).andReturn(2);
+        reset(list1, list2);
+
+        expect(list1.size()).andReturn(3);
+        expect(list2.size()).andReturn(4);
+        replay(list1, list2);
+
+        assertEquals(3, list1.size());
+        assertEquals(4, list2.size());
+
+        verify(list1, list2);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testCheckOrder() {
+        final ArrayList<Integer> list = createStrictMock(ArrayList.class);
+        checkOrder(list, false);
+        expect(list.add(1)).andReturn(true);
+        expect(list.add(3)).andReturn(true);
+        replay(list);
+        list.add(3);
+        list.add(1);
+        verify(list);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testStrictMock_Partial() throws Exception {
+        final ArrayList<Integer> list = createMockBuilder(ArrayList.class).addMockedMethod("add",
+                Object.class).createStrictMock();
+
+        expect(list.add(1)).andReturn(true);
+        expect(list.add(2)).andReturn(true);
+
+        replay(list);
+
+        assertTrue(list.isEmpty());
+
+        try {
+            list.add(2);
+            fail();
+        } catch (final AssertionError e) {
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testMock_Partial() throws Exception {
+        final ArrayList<Integer> list = createMockBuilder(ArrayList.class).addMockedMethod("add",
+                Object.class).createMock();
+
+        expect(list.add(1)).andReturn(true);
+        expect(list.add(2)).andReturn(true);
+
+        replay(list);
+
+        assertTrue(list.isEmpty());
+
+        list.add(2);
+        list.add(1);
+
+        verify(list);
+    }
+
+    @Test
+    public void testNiceMock_Partial() throws Exception {
+        final ArrayList<?> list = createMockBuilder(ArrayList.class).addMockedMethod("get").createNiceMock();
+
+        replay(list);
+
+        assertNull(list.get(0));
+        assertTrue(list.isEmpty());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testCompare() {
+        final BigDecimal expected = new BigDecimal("15.6");
+        final BigDecimal actual = new BigDecimal("15.60");
+
+        final ArrayList<BigDecimal> list = createMock(ArrayList.class);
+        expect(list.add(cmpEq(expected))).andReturn(true);
+
+        replay(list);
+
+        list.add(actual);
+
+        verify(list);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testNamedMock() throws Exception {
+        ArrayList<BigDecimal> list = createMock("mockName", ArrayList.class);
+        assertEquals("mockName", list.toString());
+        list = createStrictMock("mockName", ArrayList.class);
+        assertEquals("mockName", list.toString());
+        list = createNiceMock("mockName", ArrayList.class);
+        assertEquals("mockName", list.toString());
+
+        // Note that toString needs to be mocked if you want EasyMock default
+        // toString() behavior
+        final Method m = ArrayList.class.getMethod("toString", (Class<?>[]) null);
+
+        list = createMockBuilder(ArrayList.class).addMockedMethod(m).createMock("mockName");
+        assertEquals("mockName", list.toString());
+        list = createMockBuilder(ArrayList.class).addMockedMethod(m).createStrictMock("mockName");
+        assertEquals("mockName", list.toString());
+        list = createMockBuilder(ArrayList.class).addMockedMethod(m).createNiceMock("mockName");
+        assertEquals("mockName", list.toString());
+    }
+
+    @Test
+    public void testStrictMock() throws Exception {
+        for (final ParamEntry p : PARAMETERS) {
+            final A mock = p.getMock("createStrictMock");
+            p.test(mock);
+            testStrict(mock);
+        }
+    }
+
+    @Test
+    public void testNormalMock() throws Exception {
+        for (final ParamEntry p : PARAMETERS) {
+            final A mock = p.getMock("createMock");
+            p.test(mock);
+            testNormal(mock);
+        }
+    }
+
+    @Test
+    public void testNiceMock() throws Exception {
+        for (final ParamEntry p : PARAMETERS) {
+            final A mock = p.getMock("createNiceMock");
+            p.test(mock);
+            testNice(mock);
+        }
+    }
+
+    @Test
+    public void testCreateMockBuilder() {
+        final IMockBuilder<A> builder = createMockBuilder(A.class);
+        final A a = builder.withConstructor(int.class).withArgs(2).createMock();
+        assertEquals(2, a.i);
+    }
+
+    // 3 mock types
+
+    private static void testStrict(final A mock) {
+        reset(mock); // just in case we are not in a stable state
+        expect(mock.add(1)).andReturn(true);
+        expect(mock.add(2)).andReturn(true);
+        replay(mock);
+        try {
+            mock.add(2);
+            fail("Should be ordered");
+        } catch (final AssertionError e) {
+        }
+    }
+
+    private static void testNormal(final A mock) {
+        reset(mock); // just in case we are not in a stable state
+        expect(mock.add(1)).andReturn(true);
+        expect(mock.add(2)).andReturn(true);
+        replay(mock);
+        // unordered
+        mock.add(2);
+        mock.add(1);
+        // but not nice
+        try {
+            mock.add(3);
+            fail("Should be ordered");
+        } catch (final AssertionError e) {
+        }
+    }
+
+    private static void testNice(final A mock) {
+        reset(mock); // just in case we are not in a stable state
+        replay(mock);
+        assertFalse(mock.add(2));
+        verify(mock);
+    }
+
+    // call flavors
+
+    private static void testNamed(final A mock) {
+        assertEquals("myMock", mock.toString());
+    }
+
+    private static void testPartial_NoConstructorCalled(final A mock) {
+        // not really nice since I'm looking at the inner implementation
+        assertEquals(0, mock.i);
+    }
+
+    private static void testPartial_ConstructorCalled(final A mock) {
+        assertEquals(3, mock.i);
+    }
+}
diff --git a/tests/org/easymock/tests2/EasyMockPropertiesTest.java b/tests/org/easymock/tests2/EasyMockPropertiesTest.java
new file mode 100644
index 0000000..bb86a54
--- /dev/null
+++ b/tests/org/easymock/tests2/EasyMockPropertiesTest.java
@@ -0,0 +1,256 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+
+import org.easymock.EasyMock;
+import org.easymock.internal.EasyMockProperties;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class EasyMockPropertiesTest {
+
+    private static final String NORMAL_PATH = "target" + File.separatorChar + "test-classes";
+    private static final String CLOVER_PATH = "target" + File.separatorChar + "clover" + File.separatorChar + "test-classes";
+    private static final File PROPERTIES_FILE = new File(isCloverBuild() ? CLOVER_PATH : NORMAL_PATH, "easymock.properties");
+
+    /**
+     * Check that the test execution isn't ran by Clover. Because it it's the case, we need to generate the easymock.properties
+     * file in a different directory
+     */
+    private static boolean isCloverBuild() {
+        String surefireClasspath = System.getProperty("surefire.test.class.path");
+        if(surefireClasspath != null) {
+            return surefireClasspath.contains(CLOVER_PATH);
+        }
+        return false;
+    }
+
+    @BeforeClass
+    public static void beforeClass() throws Exception {
+        // Create an EasyMock property file for the test
+        final BufferedWriter out = new BufferedWriter(new FileWriter(PROPERTIES_FILE));
+        out.write(EasyMock.ENABLE_THREAD_SAFETY_CHECK_BY_DEFAULT + "=" + true);
+        out.newLine();
+        out.write("easymock.a=1");
+        out.newLine();
+        out.write("easymock.b=2");
+        out.newLine();
+        out.write(EasyMock.NOT_THREAD_SAFE_BY_DEFAULT + "=" + true);
+        out.newLine();
+        out.close();
+    }
+
+    @AfterClass
+    public static void afterClass() throws Exception {
+        // Cleanup the mess
+        PROPERTIES_FILE.delete();
+
+        // Make sure we reset all our mess at the end
+        resetInstance();
+    }
+
+    @Before
+    public void setup() throws Exception {
+        // Make sure to reset to prevent getting an already initialized
+        // EasyMockProperties
+        resetInstance();
+
+        // Set manually a new one
+        setEasyMockProperty("easymock.e", "7");
+
+        // Set manually an old one
+        setEasyMockProperty("easymock.c", "8");
+
+        // Overload after (will be ignored)
+        System.setProperty("easymock.h", "4");
+    }
+
+    @Test
+    public void testGetInstance() throws Exception {
+        assertExpectedValue("1", "easymock.a");
+        assertExpectedValue("8", "easymock.c");
+        assertExpectedValue("7", "easymock.e");
+        assertExpectedValue(null, "easymock.g");
+        assertExpectedValue(null, "easymock.h");
+        assertExpectedValue(null, "xxx.yyy");
+
+        assertExpectedValue(Boolean.TRUE.toString(), EasyMock.NOT_THREAD_SAFE_BY_DEFAULT);
+        assertExpectedValue(null, EasyMock.DISABLE_CLASS_MOCKING);
+    }
+
+    @Test
+    public void testGetProperty() {
+        final EasyMockProperties instance = EasyMockProperties.getInstance();
+
+        // use the default
+        assertEquals("1", instance.getProperty("easymock.a", "10"));
+        // don't use the default
+        assertEquals("10", instance.getProperty("easymock.z", "10"));
+        // null default
+        assertNull(instance.getProperty("easymock.z", null));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testSetProperty() {
+        final EasyMockProperties instance = EasyMockProperties.getInstance();
+
+        instance.setProperty("tralala.a", null);
+    }
+
+    @Test
+    public void testNoThreadContextClassLoader() throws Exception {
+        final ClassLoader old = Thread.currentThread().getContextClassLoader();
+        try {
+            resetInstance();
+
+            // Remove the context class loader
+            Thread.currentThread().setContextClassLoader(null);
+
+            // This instance will load easymock.properties from the
+            // EasyMockProperties class loader
+            EasyMockProperties.getInstance();
+
+            // And so "easymock.a" should be there
+            assertExpectedValue("1", "easymock.a");
+
+        } finally {
+            // Whatever happens, set the initial class loader back or it'll get
+            // messy
+            Thread.currentThread().setContextClassLoader(old);
+        }
+    }
+
+    @Test
+    public void testBadPropertiesFile() throws Exception {
+
+        final Boolean[] close = new Boolean[1];
+
+        // A ClassLoader that returns no easymock.properties
+        final ClassLoader cl = new ClassLoader(getClass().getClassLoader()) {
+
+            @Override
+            public InputStream getResourceAsStream(final String name) {
+                if ("easymock.properties".equals(name)) {
+                    return new InputStream() {
+                        @Override
+                        public void close() throws IOException {
+                            close[0] = Boolean.TRUE;
+                        }
+
+                        @Override
+                        public int read(final byte[] b, final int off, final int len) throws IOException {
+                            throw new IOException("Failed!");
+                        }
+
+                        @Override
+                        public int read(final byte[] b) throws IOException {
+                            throw new IOException("Failed!");
+                        }
+
+                        @Override
+                        public int read() throws IOException {
+                            throw new IOException("Failed!");
+                        }
+                    };
+                }
+                return super.getResourceAsStream(name);
+            }
+
+        };
+        final ClassLoader old = Thread.currentThread().getContextClassLoader();
+        try {
+            resetInstance();
+
+            // Remove the context class loader
+            Thread.currentThread().setContextClassLoader(cl);
+
+            try {
+                EasyMockProperties.getInstance();
+                fail("Should have an issue loading the easymock.properties file");
+            } catch (final RuntimeException e) {
+                assertEquals("Failed to read easymock.properties file", e.getMessage());
+                // Make sure the thread was closed
+                assertSame(Boolean.TRUE, close[0]);
+            }
+
+        } finally {
+            // Whatever happens, set the initial class loader back or it'll get
+            // messy
+            Thread.currentThread().setContextClassLoader(old);
+        }
+    }
+
+    @Test
+    public void testNoEasymockPropertiesFile() throws Exception {
+        // A ClassLoader that returns no easymock.properties
+        final ClassLoader cl = new ClassLoader(getClass().getClassLoader()) {
+
+            @Override
+            public InputStream getResourceAsStream(final String name) {
+                if ("easymock.properties".equals(name)) {
+                    return null;
+                }
+                return super.getResourceAsStream(name);
+            }
+
+        };
+        final ClassLoader old = Thread.currentThread().getContextClassLoader();
+        try {
+            resetInstance();
+
+            // Set our class loader
+            Thread.currentThread().setContextClassLoader(cl);
+
+            // This instance will try to load easymock.properties with our
+            // custom class loader and so won't find it
+            EasyMockProperties.getInstance();
+
+            // And so it shouldn't find "easymock.a"
+            assertExpectedValue(null, "easymock.a");
+
+        } finally {
+            // Whatever happens, set the initial class loader back or it'll get
+            // messy
+            Thread.currentThread().setContextClassLoader(old);
+        }
+    }
+
+    private static void resetInstance() throws NoSuchFieldException, IllegalAccessException {
+        // Cheat and make the singleton uninitialized
+        final Field field = EasyMockProperties.class.getDeclaredField("instance");
+        field.setAccessible(true);
+        field.set(null, null);
+    }
+
+    private static void assertExpectedValue(final String expected, final String key) {
+        assertEquals(expected, getEasyMockProperty(key));
+    }
+}
diff --git a/tests/org/easymock/tests2/EasyMockRunnerTest.java b/tests/org/easymock/tests2/EasyMockRunnerTest.java
new file mode 100644
index 0000000..b8c8290
--- /dev/null
+++ b/tests/org/easymock/tests2/EasyMockRunnerTest.java
@@ -0,0 +1,112 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import org.easymock.EasyMockRunner;
+import org.easymock.EasyMockSupport;
+import org.easymock.TestSubject;
+import org.easymock.Mock;
+import org.easymock.MockType;
+import org.easymock.tests.BaseEasyMockRunnerTest;
+import org.easymock.tests.IMethods;
+import org.easymock.tests.IVarArgs;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+ at RunWith(EasyMockRunner.class)
+public class EasyMockRunnerTest extends BaseEasyMockRunnerTest {
+
+    @Mock
+    private IMethods standardMock;
+
+    @Mock(type = MockType.NICE)
+    private IMethods typedMock;
+
+    @Mock(name = "name1")
+    private IMethods namedMock;
+
+    @Mock(name = "name2", type = MockType.NICE)
+    private IMethods namedAndTypedMock;
+
+    @Test
+    public void testMocksWithSupport() {
+        expect(standardMock.oneArg(true)).andReturn("1");
+        expect(namedMock.oneArg(true)).andReturn("2");
+        replayAll();
+        assertNull(typedMock.oneArg("0"));
+        assertNull(namedAndTypedMock.oneArg("0"));
+        assertEquals("1", standardMock.oneArg(true));
+        assertEquals("2", namedMock.oneArg(true));
+        verifyAll();
+        assertEquals("EasyMock for interface org.easymock.tests.IMethods", standardMock.toString());
+        assertEquals("name1", namedMock.toString());
+        assertEquals("EasyMock for interface org.easymock.tests.IMethods", typedMock.toString());
+        assertEquals("name2", namedAndTypedMock.toString());
+    }
+
+    private static class ToInject {
+        protected IMethods m1;
+        protected IMethods m2;
+        protected IVarArgs v;
+        protected String a;
+        protected final IVarArgs f = null;
+        protected static IVarArgs s;
+    }
+
+    private static class ToInjectTest {
+        @Mock
+        protected IMethods m;
+        @Mock
+        protected IVarArgs v;
+        @TestSubject
+        protected ToInject toInject = new ToInject();
+    }
+
+    @Test
+    public void testInjectMocks() {
+        ToInjectTest test = new ToInjectTest();
+        EasyMockSupport.injectMocks(test);
+        assertSame(test.m, test.toInject.m1);
+        assertSame(test.m, test.toInject.m2);
+        assertSame(test.v, test.toInject.v);
+        assertNull(test.toInject.a);
+        assertNull(test.toInject.f);
+        assertNull(ToInject.s);
+    }
+
+    private static class ToInjectDuplicateTest {
+        @Mock(name="a")
+        protected IMethods m;
+        @Mock(name="b")
+        protected IMethods v;
+        @TestSubject
+        protected ToInject toInject = new ToInject();
+    }
+
+    @Test
+    public void testInjectDuplicate() {
+        ToInjectDuplicateTest test = new ToInjectDuplicateTest();
+        try {
+            EasyMockSupport.injectMocks(test);
+        }
+        catch (RuntimeException e) {
+            assertEquals("At least two mocks can be assigned to protected org.easymock.tests.IMethods org.easymock.tests2.EasyMockRunnerTest$ToInject.m1: a and b", e.getMessage());
+        }
+    }
+}
diff --git a/tests/org/easymock/tests2/EasyMockSupportClassTest.java b/tests/org/easymock/tests2/EasyMockSupportClassTest.java
new file mode 100644
index 0000000..12a8759
--- /dev/null
+++ b/tests/org/easymock/tests2/EasyMockSupportClassTest.java
@@ -0,0 +1,206 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.core.Is.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Method;
+
+import org.easymock.ConstructorArgs;
+import org.easymock.EasyMockSupport;
+import org.easymock.IMocksControl;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+ at SuppressWarnings("deprecation")
+public class EasyMockSupportClassTest extends EasyMockSupport {
+
+    public static class ToMock {
+        public int foo() {
+            return 5;
+        }
+    }
+
+    private Method foo;
+
+    private ConstructorArgs args;
+
+    @Before
+    public void setUp() throws Exception {
+        foo = ToMock.class.getMethod("foo");
+        args = new ConstructorArgs(ToMock.class.getConstructor());
+    }
+
+    @Test
+    public void testCreateStrictControl() {
+        final IMocksControl ctrl = createStrictControl();
+        assertThat(ctrl.createMock(ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateControl() {
+        final IMocksControl ctrl = createControl();
+        assertThat(ctrl.createMock(ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceControl() {
+        final IMocksControl ctrl = createNiceControl();
+        assertThat(ctrl.createMock(ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateStrictMockClassOfTMethodArray() {
+        assertThat(createStrictMock(ToMock.class, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateStrictMockStringClassOfTMethodArray() {
+        assertThat(createStrictMock("myMock", ToMock.class, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateStrictMockClassOfTConstructorArgsMethodArray() {
+        assertThat(createStrictMock(ToMock.class, args, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateStrictMockStringClassOfTConstructorArgsMethodArray() {
+        assertThat(createStrictMock("myMock", ToMock.class, args, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateMockClassOfTMethodArray() {
+        assertThat(createMock(ToMock.class, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateMockStringClassOfTMethodArray() {
+        assertThat(createMock("myMock", ToMock.class, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateMockClassOfTConstructorArgsMethodArray() {
+        assertThat(createMock(ToMock.class, args, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateMockStringClassOfTConstructorArgsMethodArray() {
+        assertThat(createMock("myMock", ToMock.class, args, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceMockClassOfTMethodArray() {
+        assertThat(createNiceMock(ToMock.class, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceMockStringClassOfTMethodArray() {
+        assertThat(createNiceMock("myMock", ToMock.class, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceMockClassOfTConstructorArgsMethodArray() {
+        assertThat(createNiceMock(ToMock.class, args, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceMockStringClassOfTConstructorArgsMethodArray() {
+        assertThat(createNiceMock("myMock", ToMock.class, args, foo), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateStrictMockClassOfT() {
+        assertThat(createStrictMock(ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateStrictMockStringClassOfT() {
+        assertThat(createStrictMock("myMock", ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateMockClassOfT() {
+        assertThat(createMock(ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateMockStringClassOfT() {
+        assertThat(createMock("myMock", ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceMockClassOfT() {
+        assertThat(createNiceMock(ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testCreateNiceMockStringClassOfT() {
+        assertThat(createNiceMock("myMock", ToMock.class), is(ToMock.class));
+    }
+
+    @Test
+    public void testAll() {
+        final ToMock t = createMock(ToMock.class);
+        expect(t.foo()).andReturn(1);
+        replayAll();
+        t.foo();
+        verifyAll();
+        resetAll();
+        resetAllToDefault();
+        resetAllToNice();
+        resetAllToStrict();
+    }
+
+    @Test
+    public void testCreateMockBuilder() {
+        final ToMock t = createMockBuilder(ToMock.class).addMockedMethod(foo).createMock();
+        expect(t.foo()).andReturn(1);
+        replayAll();
+        assertEquals(1, t.foo());
+        verifyAll();
+    }
+
+    @Test
+    public void testCreateMockBuilder_existingControl() {
+        final IMocksControl ctrl = createControl(); // ctrl registered once here
+        final ToMock t = createMockBuilder(ToMock.class).addMockedMethod(foo).createMock(ctrl); // should not be registered a second time here
+        expect(t.foo()).andReturn(1);
+        replayAll();
+        assertEquals(1, t.foo());
+        verifyAll();
+    }
+
+    @Test
+    public void testAllMockBuilderFlavors() {
+        final ToMock t1 = createMockBuilder(ToMock.class).addMockedMethod(foo).createMock();
+        final ToMock t2 = createMockBuilder(ToMock.class).addMockedMethod(foo).createNiceMock();
+        final ToMock t3 = createMockBuilder(ToMock.class).addMockedMethod(foo).createStrictMock();
+        expect(t1.foo()).andReturn(1);
+        expect(t2.foo()).andReturn(2);
+        expect(t3.foo()).andReturn(3);
+        replayAll();
+        assertEquals(1, t1.foo());
+        assertEquals(2, t2.foo());
+        assertEquals(3, t3.foo());
+        verifyAll();
+    }
+}
diff --git a/tests/org/easymock/tests2/EasyMockSupportTest.java b/tests/org/easymock/tests2/EasyMockSupportTest.java
new file mode 100644
index 0000000..8a73385
--- /dev/null
+++ b/tests/org/easymock/tests2/EasyMockSupportTest.java
@@ -0,0 +1,273 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.EasyMockSupport;
+import org.easymock.IMocksControl;
+import org.easymock.tests.IMethods;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class EasyMockSupportTest extends EasyMockSupport {
+
+    private IMethods mock1;
+
+    private IMethods mock2;
+
+    @Test
+    public void testCreateControl() {
+        final IMocksControl ctrl = createControl();
+        mock1 = ctrl.createMock(IMethods.class);
+        mock2 = ctrl.createMock(IMethods.class);
+        testDefaultMock();
+    }
+
+    @Test
+    public void testCreateMock() {
+        mock1 = createMock(IMethods.class);
+        mock2 = createMock(IMethods.class);
+        testDefaultMock();
+    }
+
+    @Test
+    public void testCreateNamedMock() {
+        mock1 = createMock("a", IMethods.class);
+        mock2 = createMock("b", IMethods.class);
+        testDefaultMock();
+        assertEquals("a", mock1.toString());
+        assertEquals("b", mock2.toString());
+    }
+
+    private void testDefaultMock() {
+        mock1.simpleMethod();
+        expect(mock1.oneArg(true)).andReturn("foo");
+        mock2.simpleMethod();
+        expect(mock2.oneArg(false)).andReturn("foo");
+        replayAll();
+        assertEquals("foo", mock1.oneArg(true));
+        assertEquals("foo", mock2.oneArg(false));
+        mock2.simpleMethod();
+        mock1.simpleMethod();
+        verifyAll();
+    }
+
+    @Test
+    public void testCreateNiceControl() {
+        final IMocksControl ctrl = createNiceControl();
+        mock1 = ctrl.createMock(IMethods.class);
+        mock2 = ctrl.createMock(IMethods.class);
+        testNiceMock();
+    }
+
+    @Test
+    public void testCreateNiceMock() {
+        mock1 = createNiceMock(IMethods.class);
+        mock2 = createNiceMock(IMethods.class);
+        testNiceMock();
+    }
+
+    @Test
+    public void testCreateNamedNiceMock() {
+        mock1 = createNiceMock("a", IMethods.class);
+        mock2 = createNiceMock("b", IMethods.class);
+        testNiceMock();
+        assertEquals("a", mock1.toString());
+        assertEquals("b", mock2.toString());
+    }
+
+    private void testNiceMock() {
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock2.oneArg(false)).andReturn("foo");
+        replayAll();
+        assertNull(mock1.oneArg(false));
+        assertNull(mock2.oneArg(true));
+        assertEquals("foo", mock1.oneArg(true));
+        assertEquals("foo", mock2.oneArg(false));
+        verifyAll();
+    }
+
+    @Test
+    public void testCreateStrictControl() {
+        final IMocksControl ctrl = createStrictControl();
+        mock1 = ctrl.createMock(IMethods.class);
+        mock2 = ctrl.createMock(IMethods.class);
+        testStrictMock();
+        resetAll();
+        mock1.simpleMethod();
+        mock2.simpleMethod();
+        replayAll();
+        try {
+            mock2.simpleMethod();
+            fail("Should be ordered");
+        } catch (final AssertionError e) {
+        }
+        mock1.simpleMethod();
+        mock2.simpleMethod();
+        verifyAll();
+    }
+
+    @Test
+    public void testCreateStrictMock() {
+        mock1 = createStrictMock(IMethods.class);
+        mock2 = createStrictMock(IMethods.class);
+        testStrictMock();
+    }
+
+    @Test
+    public void testCreateNamedStrictMock() {
+        mock1 = createStrictMock("a", IMethods.class);
+        mock2 = createStrictMock("b", IMethods.class);
+        testStrictMock();
+        assertEquals("a", mock1.toString());
+        assertEquals("b", mock2.toString());
+    }
+
+    private void testStrictMock() {
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock1.oneArg(false)).andReturn("foo");
+        expect(mock2.oneArg(false)).andReturn("foo");
+        expect(mock2.oneArg(true)).andReturn("foo");
+        replayAll();
+        try {
+            mock1.oneArg(false);
+            fail("Should be ordered");
+        } catch (final AssertionError e) {
+        }
+        mock1.oneArg(true);
+        mock1.oneArg(false);
+        try {
+            mock2.oneArg(true);
+            fail("Should be ordered");
+        } catch (final AssertionError e) {
+        }
+        mock2.oneArg(false);
+        mock2.oneArg(true);
+        verifyAll();
+    }
+
+    @Test
+    public void testVerify() {
+        mock1 = createMock(IMethods.class);
+        mock2 = createMock(IMethods.class);
+        mock1.simpleMethod();
+        mock2.simpleMethod();
+        replayAll();
+        mock1.simpleMethod();
+        mock2.simpleMethod();
+        verifyAll();
+        resetAll();
+        mock1.simpleMethod();
+        mock2.simpleMethod();
+        resetAll();
+        replayAll();
+        verifyAll();
+    }
+
+    @Test
+    public void defaultResetToNice() {
+        mock1 = createMock(IMethods.class);
+        mock2 = createMock(IMethods.class);
+
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock2.oneArg(false)).andReturn("foo");
+
+        replayAll();
+
+        resetAllToNice();
+
+        replayAll();
+
+        assertNull(mock1.oneArg(true));
+        assertNull(mock2.oneArg(false));
+
+        verifyAll();
+    }
+
+    @Test
+    public void strictResetToDefault() {
+        mock1 = createStrictMock(IMethods.class);
+        mock2 = createStrictMock(IMethods.class);
+
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock1.oneArg(false)).andReturn("foo");
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock1.oneArg(false)).andReturn("foo");
+
+        replayAll();
+
+        resetAllToDefault();
+
+        expect(mock1.oneArg(false)).andReturn("foo");
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock2.oneArg(false)).andReturn("foo");
+        expect(mock2.oneArg(true)).andReturn("foo");
+
+        replayAll();
+
+        assertEquals("foo", mock1.oneArg(false));
+        assertEquals("foo", mock1.oneArg(true));
+        assertEquals("foo", mock2.oneArg(false));
+        assertEquals("foo", mock2.oneArg(true));
+
+        verifyAll();
+    }
+
+    @Test
+    public void niceToStrict() {
+        final IMethods mock1 = createNiceMock(IMethods.class);
+        final IMethods mock2 = createNiceMock(IMethods.class);
+
+        expect(mock1.oneArg(false)).andReturn("foo");
+        expect(mock2.oneArg(false)).andReturn("foo");
+
+        replayAll();
+
+        assertNull(mock1.oneArg(true));
+        assertNull(mock2.oneArg(true));
+
+        resetAllToStrict();
+
+        expect(mock1.oneArg(false)).andReturn("foo");
+        expect(mock1.oneArg(true)).andReturn("foo");
+        expect(mock2.oneArg(false)).andReturn("foo");
+        expect(mock2.oneArg(true)).andReturn("foo");
+
+        replayAll();
+
+        try {
+            mock1.oneArg(true);
+            fail("Should be strict");
+        } catch (final AssertionError e) {
+        }
+        try {
+            mock2.oneArg(true);
+            fail("Should be strict");
+        } catch (final AssertionError e) {
+        }
+
+        assertEquals("foo", mock1.oneArg(false));
+        assertEquals("foo", mock1.oneArg(true));
+        assertEquals("foo", mock2.oneArg(false));
+        assertEquals("foo", mock2.oneArg(true));
+
+        verifyAll();
+    }
+}
diff --git a/tests/org/easymock/tests2/FilteringRule.java b/tests/org/easymock/tests2/FilteringRule.java
new file mode 100644
index 0000000..b881a86
--- /dev/null
+++ b/tests/org/easymock/tests2/FilteringRule.java
@@ -0,0 +1,165 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+public class FilteringRule implements TestRule {
+
+    private final String[] filteredPackages;
+
+    public FilteringRule(final String... filteredPackages) {
+        this.filteredPackages = filteredPackages;
+    }
+
+    public Statement apply(final Statement base, final Description description) {
+        return new FilteringStatement(base, description, filteredPackages);
+    }
+
+}
+
+class FilteringClassLoader extends ClassLoader {
+
+    private static final String[] packagesToBeDeferred = new String[] { "org.hamcrest.", "java.", "sun.",
+            "org.junit." };
+
+    private final Collection<String> ignoredPackages;
+
+    private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
+
+    public FilteringClassLoader(final Collection<String> ignoredPackages) {
+        this.ignoredPackages = ignoredPackages;
+    }
+
+    @Override
+    protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
+        if (isIgnored(name)) {
+            throw new ClassNotFoundException(name);
+        }
+        Class<?> clazz = classes.get(name);
+        if (clazz != null) {
+            return clazz;
+        }
+
+        if (shouldBeDeferred(name)) {
+            return super.loadClass(name, resolve);
+        }
+
+        try {
+            clazz = loadClass0(name);
+        } catch (final IOException e) {
+            throw new ClassNotFoundException("Can't load " + name, e);
+        }
+
+        if (resolve) {
+            resolveClass(clazz);
+        }
+
+        classes.put(name, clazz);
+        return clazz;
+    }
+
+    private boolean shouldBeDeferred(final String name) {
+        for (final String pack : packagesToBeDeferred) {
+            if (name.startsWith(pack)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Class<?> loadClass0(final String name) throws IOException, ClassNotFoundException {
+        final String path = name.replace('.', '/') + ".class";
+        InputStream in = null;
+        ByteArrayOutputStream out = null;
+
+        try {
+            in = getResourceAsStream(path);
+            if (in == null) {
+                throw new ClassNotFoundException(name);
+            }
+            out = new ByteArrayOutputStream();
+
+            int one;
+            while ((one = in.read()) != -1) {
+                out.write((byte) one);
+            }
+
+            out.flush();
+
+            final byte bytes[] = out.toByteArray();
+            return bytes == null ? null : defineClass(name, bytes, 0, bytes.length);
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    private boolean isIgnored(final String name) {
+        for (final String s : ignoredPackages) {
+            if (name.startsWith(s)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
+
+class FilteringStatement extends Statement {
+
+    private final Statement innerStatement;
+
+    private final Description description; // Description of the tested method
+
+    private final String[] filteredPackages;
+
+    public FilteringStatement(final Statement base, final Description description,
+            final String[] filteredPackages) {
+        this.innerStatement = base;
+        this.description = description;
+        this.filteredPackages = filteredPackages;
+    }
+
+    @Override
+    public void evaluate() throws Throwable {
+        final FilteringClassLoader cl = new FilteringClassLoader(Arrays.asList(filteredPackages));
+        final Class<?> c = cl.loadClass(description.getTestClass().getName());
+        final Object test = c.newInstance();
+        final Method m = c.getMethod(description.getMethodName());
+        try {
+            m.invoke(test);
+        } catch (final InvocationTargetException e) {
+            throw e.getTargetException();
+        }
+    }
+
+}
diff --git a/tests/org/easymock/tests2/MockBuilderTest.java b/tests/org/easymock/tests2/MockBuilderTest.java
new file mode 100644
index 0000000..7cadc2f
--- /dev/null
+++ b/tests/org/easymock/tests2/MockBuilderTest.java
@@ -0,0 +1,355 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import java.util.ArrayList;
+
+import org.easymock.ConstructorArgs;
+import org.easymock.EasyMockSupport;
+import org.easymock.IMocksControl;
+import org.easymock.MockType;
+import org.easymock.internal.MockBuilder;
+import org.easymock.internal.MocksControl;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class MockBuilderTest {
+
+    private static class A {
+        public final void foo(final String s) {
+        }
+    }
+
+    private MockBuilder<ArrayList<String>> builder;
+
+    private ArrayList<String> mock;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Before
+    public void setUp() throws Exception {
+        builder = new MockBuilder(ArrayList.class);
+    }
+
+    @Test
+    public void testAddMockedMethod() throws NoSuchMethodException {
+        builder.addMockedMethod(ArrayList.class.getMethod("size"))
+                .addMockedMethod("contains")
+                .addMockedMethod("add", Object.class)
+                .addMockedMethods("clear", "isEmpty")
+                .addMockedMethods(ArrayList.class.getMethod("get", int.class),
+                        ArrayList.class.getMethod("indexOf", Object.class));
+
+        mock = builder.createMock();
+
+        expect(mock.size()).andReturn(3);
+        expect(mock.contains("test")).andReturn(true);
+        expect(mock.add("added")).andReturn(true);
+        mock.clear();
+        expect(mock.isEmpty()).andReturn(false);
+        expect(mock.get(1)).andReturn("result");
+        expect(mock.indexOf("t")).andReturn(2);
+
+        replay(mock);
+
+        assertEquals(3, mock.size());
+        assertEquals(true, mock.contains("test"));
+        assertEquals(true, mock.add("added"));
+        mock.clear();
+        assertEquals(false, mock.isEmpty());
+        assertEquals("result", mock.get(1));
+        assertEquals(2, mock.indexOf("t"));
+
+        verify(mock);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddMethod_NotExisting() {
+        builder.addMockedMethod("..");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testAddMethodWithParams_NotExisting() {
+        builder.addMockedMethod("..", String.class);
+    }
+
+    @Test
+    public void testAddMethod_Final() throws Exception {
+        final String errorMessage = "Final methods can't be mocked";
+        final MockBuilder<A> builder = new MockBuilder<A>(A.class);
+        try {
+            builder.addMockedMethod(A.class.getMethod("foo", String.class));
+            fail("sholdn't be allowed to be mocked");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(errorMessage, e.getMessage());
+        }
+        try {
+            builder.addMockedMethod("foo");
+            fail("sholdn't be allowed to be mocked");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(errorMessage, e.getMessage());
+        }
+        try {
+            builder.addMockedMethod("foo", String.class);
+            fail("sholdn't be allowed to be mocked");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(errorMessage, e.getMessage());
+        }
+    }
+
+    @Test
+    public void testAddMethods_Final() throws Exception {
+        final String errorMessage = "Final methods can't be mocked";
+        final MockBuilder<A> builder = new MockBuilder<A>(A.class);
+        try {
+            builder.addMockedMethods(A.class.getMethod("foo", String.class));
+            fail("sholdn't be allowed to be mocked");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(errorMessage, e.getMessage());
+        }
+        try {
+            builder.addMockedMethods("foo");
+            fail("sholdn't be allowed to be mocked");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(errorMessage, e.getMessage());
+        }
+    }
+
+    @Test
+    public void testWithConstructorParams() {
+        builder.withConstructor(int.class).withArgs(-3);
+        try {
+            builder.createMock();
+            fail("instantiation should fail because of negative");
+        } catch (final RuntimeException e) {
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWithConstructor_WrongClass() {
+        builder.withConstructor(long.class);
+    }
+
+    @Test
+    public void testWithEmptyConstructor() throws Exception {
+        final EmptyConstructor instance = new MockBuilder<EmptyConstructor>(EmptyConstructor.class)
+                .withConstructor().createMock();
+        assertEquals("foo", instance.setByConstructor);
+    }
+
+    public static class EmptyConstructor {
+        private final String setByConstructor;
+
+        public EmptyConstructor() {
+            this.setByConstructor = "foo";
+        }
+    }
+
+    @Test
+    public void testWithEmptyConstructor_NoEmptyConstructor() throws Exception {
+        try {
+            createMockBuilder(Integer.class).withConstructor().createMock();
+            fail("no empty constructor should be found");
+        } catch (final IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testWithConstructor() throws NoSuchMethodException {
+        builder.withConstructor(ArrayList.class.getConstructor(int.class)).withArgs(-3);
+        try {
+            builder.createMock();
+            fail("instantiation should fail because of negative");
+        } catch (final RuntimeException e) {
+        }
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testWithConstructor_Twice() {
+        builder.withConstructor(int.class).withConstructor(int.class);
+    }
+
+    @Test
+    public void testWithConstructorConstructorArgs() throws NoSuchMethodException {
+        final ConstructorArgs args = new ConstructorArgs(ArrayList.class.getConstructor(int.class),
+                Integer.valueOf(-3));
+        builder.withConstructor(args);
+        try {
+            builder.createMock();
+            fail("instantiation should fail because of negative");
+        } catch (final RuntimeException e) {
+        }
+    }
+
+    @Test
+    public void testWithConstructorWithArgs() throws NoSuchMethodException {
+        builder.withConstructor(-3);
+        try {
+            builder.createMock();
+            fail("instantiation should fail because of negative");
+        } catch (final RuntimeException e) {
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWithConstructorWithArgs_NotExisting() throws NoSuchMethodException {
+        builder.withConstructor("string");
+    }
+
+    @Test
+    public void testWithArgsTwice() {
+        try {
+            builder.withConstructor(int.class).withArgs(3).withArgs(2);
+            fail("withArgs called twice");
+        } catch (final IllegalStateException e) {
+            assertEquals("Trying to define the constructor arguments more than once.", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testWithArgs_WithoutConstructor() {
+        try {
+            builder.withArgs(2);
+            fail("withArgs without constructor");
+        } catch (final IllegalStateException e) {
+            assertEquals("Trying to define constructor arguments without first setting their type.",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void testCreateMockIMocksControl() {
+        final IMocksControl ctrl = createControl();
+        mock = builder.createMock(ctrl);
+        assertSame(MocksControl.getControl(mock), ctrl);
+    }
+
+    @Test
+    public void testCreateMock() {
+        mock = builder.addMockedMethod("size").addMockedMethod("toString").createMock();
+        replay(mock);
+        try {
+            mock.size();
+            fail("Unexpected call");
+        } catch (final AssertionError e) {
+        }
+    }
+
+    @Test
+    public void testCreateNiceMock() {
+        mock = builder.addMockedMethod("size").addMockedMethod("toString").createNiceMock();
+        replay(mock);
+        assertEquals(0, mock.size());
+        verify(mock);
+    }
+
+    @Test
+    public void testCreateStrictMock() {
+        mock = builder.addMockedMethod("size").addMockedMethod("clear").addMockedMethod("toString")
+                .createStrictMock();
+        expect(mock.size()).andReturn(1);
+        mock.clear();
+        replay(mock);
+        try {
+            mock.clear();
+            fail("Unexpected call");
+        } catch (final AssertionError e) {
+        }
+    }
+
+    @Test
+    public void testCreateMockStringIMocksControl() {
+        final IMocksControl ctrl = createControl();
+        mock = builder.addMockedMethod("toString").createMock("myName", ctrl);
+        assertSame(MocksControl.getControl(mock), ctrl);
+        assertTrue(mock.toString().contains("myName"));
+    }
+
+    @Test
+    public void testCreateMockString() {
+        mock = builder.addMockedMethod("size").addMockedMethod("toString").createMock("myName");
+        replay(mock);
+        try {
+            mock.size();
+            fail("Unexpected call");
+        } catch (final AssertionError e) {
+            assertTrue(e.getMessage().contains("myName"));
+        }
+    }
+
+    @Test
+    public void testCreateNiceMockString() {
+        mock = builder.addMockedMethod("size").addMockedMethod("toString").createNiceMock("myName");
+        replay(mock);
+        assertEquals(0, mock.size());
+        verify(mock);
+        assertTrue(mock.toString().contains("myName"));
+    }
+
+    @Test
+    public void testCreateStrictMockString() throws Throwable {
+        mock = builder.addMockedMethod("size").addMockedMethod("clear").addMockedMethod("toString")
+                .createStrictMock("myName");
+        expect(mock.size()).andReturn(1);
+        mock.clear();
+        replay(mock);
+        try {
+            mock.clear();
+            fail("Unexpected call");
+        } catch (final AssertionError e) {
+            assertTrue(e.getMessage().contains("myName"));
+        }
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testCreateMock_ConstructorWithoutArgs() {
+        builder.withConstructor(int.class).createMock();
+    }
+
+    @Test
+    public void testWithMockSupport() {
+        EasyMockSupport support = new EasyMockSupport();
+        MockBuilderTest a = support.createMockBuilder(MockBuilderTest.class).addMockedMethods("myMethod", "toString").createMock(MockType.NICE);
+        expect(a.myMethod(2)).andReturn(1);
+        support.replayAll();
+        assertEquals(a.myMethod(2), 1);
+        assertEquals(a.myMethod(3), 0);
+        support.verifyAll();
+        assertEquals("EasyMock for class org.easymock.tests2.MockBuilderTest", a.toString());
+    }
+
+    @Test
+    public void testWithMockSupportNamed() {
+        EasyMockSupport support = new EasyMockSupport();
+        MockBuilderTest a = support.createMockBuilder(MockBuilderTest.class).addMockedMethods("myMethod", "toString").createMock("foo", MockType.NICE);
+        expect(a.myMethod(2)).andReturn(1);
+        support.replayAll();
+        assertEquals(a.myMethod(2), 1);
+        assertEquals(a.myMethod(3), 0);
+        support.verifyAll();
+        assertEquals("foo", a.toString());
+    }
+
+    public int myMethod(int i) {
+        return i;
+    }
+
+}
diff --git a/tests/org/easymock/tests2/MockedExceptionTest.java b/tests/org/easymock/tests2/MockedExceptionTest.java
new file mode 100644
index 0000000..ab9b613
--- /dev/null
+++ b/tests/org/easymock/tests2/MockedExceptionTest.java
@@ -0,0 +1,122 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class MockedExceptionTest {
+
+    @Test
+    public void testMockedException() {
+        final RuntimeException expected = createNiceMock(RuntimeException.class);
+        final CharSequence c = createMock(CharSequence.class);
+        expect(c.length()).andStubThrow(expected);
+        replay(c, expected);
+
+        try {
+            c.length(); // fillInStackTrace will be called internally here
+        } catch (final RuntimeException actual) {
+            assertSame(expected, actual);
+        }
+
+        verify(c, expected);
+    }
+
+    @Test
+    public void testExplicitFillInStackTrace() {
+
+        final RuntimeException expected = createNiceMock(RuntimeException.class);
+        final RuntimeException myException = new RuntimeException();
+        expect(expected.fillInStackTrace()).andReturn(myException);
+
+        final CharSequence c = createMock(CharSequence.class);
+        expect(c.length()).andStubThrow(expected);
+
+        replay(c, expected);
+
+        try {
+            c.length(); // fillInStackTrace wont' be called internally
+        } catch (final RuntimeException actual) {
+            assertSame(myException, actual.fillInStackTrace()); // so the fillInStackTrace recording is still valid
+            assertSame(expected, actual);
+        }
+
+        verify(c, expected);
+    }
+
+    private static int check = 2;
+
+    private static class MyException extends RuntimeException {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public synchronized Throwable fillInStackTrace() {
+            check = 4;
+            return super.fillInStackTrace();
+        }
+
+    }
+
+    @Test
+    public void testNotMockedFillInStackTrace() {
+
+        final RuntimeException expected = createMockBuilder(MyException.class)
+                .createNiceMock();
+
+        final CharSequence c = createMock(CharSequence.class);
+        expect(c.length()).andStubThrow(expected);
+
+        replay(c, expected);
+
+        try {
+            c.length(); // fillInStackTrace won't be called internally
+        } catch (final RuntimeException actual) {
+            assertSame(expected, actual);
+            assertSame("fillInStackTrace should have been called normally since it isn't mocked", expected,
+                    actual.fillInStackTrace());
+            assertEquals("The original method was called", 4, check);
+        }
+
+        verify(c, expected);
+    }
+
+    @Test
+    public void testRealException() {
+
+        final RuntimeException expected = new RuntimeException();
+
+        final CharSequence c = createMock(CharSequence.class);
+        expect(c.length()).andStubThrow(expected);
+
+        replay(c);
+
+        try {
+            c.length(); // fillInStackTrace will be called internally here
+        } catch (final RuntimeException actual) {
+            assertSame(expected, actual);
+            assertEquals("fillInStackTrace should have been called normally",
+                    "org.easymock.internal.MockInvocationHandler", actual.getStackTrace()[0].getClassName());
+        }
+
+        verify(c);
+    }
+}
diff --git a/tests/org/easymock/tests2/MocksControlTest.java b/tests/org/easymock/tests2/MocksControlTest.java
new file mode 100644
index 0000000..a83f253
--- /dev/null
+++ b/tests/org/easymock/tests2/MocksControlTest.java
@@ -0,0 +1,199 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.ConstructorArgs;
+import org.easymock.IMocksControl;
+import org.easymock.MockType;
+import org.easymock.internal.MocksControl;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author Henri Tremblay
+ */
+public class MocksControlTest {
+
+    public static class A {
+        int i = 1;
+
+        public A(final int i) {
+            this.i = i;
+        }
+
+        public int foo() {
+            return bar();
+        }
+
+        public int bar() {
+            return i;
+        }
+
+        public boolean add(final int i) {
+            this.i += i;
+            return true;
+        }
+    }
+
+    @Test
+    public void testMocksControl_Interface() {
+        final IMocksControl ctrl = createControl();
+        final List<?> list = ctrl.createMock(List.class);
+        testList(ctrl, list);
+    }
+
+    @Test
+    public void testMocksControl_Class() {
+        final IMocksControl ctrl = createControl();
+        final ArrayList<?> list = ctrl.createMock(ArrayList.class);
+        testList(ctrl, list);
+    }
+
+    @Test
+    public void testMocksControl_Class_WithName() {
+        final IMocksControl ctrl = createControl();
+        final ArrayList<?> list = ctrl.createMock("myMock", ArrayList.class);
+        testList(ctrl, list);
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testMocksControl_PartialMock_NoConstructorCalled() throws Exception {
+        final IMocksControl ctrl = createControl();
+        final A a = ctrl.createMock(A.class, A.class.getMethod("bar", new Class[0]), A.class.getMethod(
+                "toString", new Class[0]));
+
+        assertEquals("No constructor called so should not be initialized", 0, a.i);
+        expect(a.bar()).andReturn(5);
+        replay(a);
+        assertEquals("foo isn't mocked so it will call bar which return 5", 5, a.foo());
+        verify(a);
+
+        assertEquals("EasyMock for class org.easymock.tests2.MocksControlTest$A", a.toString());
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testMocksControl_NamedPartialMock_NoConstructorCalled() throws Exception {
+        final IMocksControl ctrl = createControl();
+        final A a = ctrl.createMock("myMock", A.class, A.class.getMethod("bar", new Class[0]), A.class
+                .getMethod("toString", new Class[0]));
+
+        assertEquals("No constructor called so should not be initialized", 0, a.i);
+        expect(a.bar()).andReturn(5);
+        replay(a);
+        assertEquals("foo isn't mocked so it will call bar which return 5", 5, a.foo());
+        verify(a);
+
+        assertEquals("myMock", a.toString());
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testMocksControl_PartialMock_ConstructorCalled() throws Exception {
+        final IMocksControl ctrl = createControl();
+
+        final ConstructorArgs args = new ConstructorArgs(A.class.getConstructor(Integer.TYPE), 6);
+
+        final A a = ctrl.createMock(A.class, args, A.class.getMethod("bar", new Class[0]), A.class.getMethod(
+                "toString", new Class[0]));
+
+        assertEquals("Constructor called so should be initialized", 6, a.i);
+        expect(a.bar()).andReturn(5);
+        replay(a);
+        assertEquals("foo isn't mocked so it will call bar which return 5", 5, a.foo());
+        verify(a);
+
+        assertEquals("EasyMock for class org.easymock.tests2.MocksControlTest$A", a.toString());
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testMocksControl_NamedPartialMock_ConstructorCalled() throws Exception {
+        final IMocksControl ctrl = createControl();
+
+        final ConstructorArgs args = new ConstructorArgs(A.class.getConstructor(Integer.TYPE), 6);
+
+        final A a = ctrl.createMock("myMock", A.class, args, A.class.getMethod("bar", new Class[0]), A.class
+                .getMethod("toString", new Class[0]));
+
+        assertEquals("Constructor called so should be initialized", 6, a.i);
+        expect(a.bar()).andReturn(5);
+        replay(a);
+        assertEquals("foo isn't mocked so it will call bar which return 5", 5, a.foo());
+        verify(a);
+
+        assertEquals("myMock", a.toString());
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void testInterfaceForbidden_PartialMock() throws Exception {
+        final ConstructorArgs args = new ConstructorArgs(ArrayList.class.getConstructor(Integer.TYPE), 6);
+        final Method[] methods = new Method[] { List.class.getMethod("size", new Class[0]) };
+
+        final IMocksControl ctrl = createControl();
+
+        try {
+            ctrl.createMock(List.class, methods);
+            fail("partial mocking on interface shouln't be allowed");
+        } catch (final IllegalArgumentException e) {
+        }
+
+        try {
+            ctrl.createMock(List.class, args, methods);
+            fail("partial mocking on interface shouln't be allowed");
+        } catch (final IllegalArgumentException e) {
+        }
+
+        try {
+            ctrl.createMock("myMock", List.class, methods);
+            fail("partial mocking on interface shouln't be allowed");
+        } catch (final IllegalArgumentException e) {
+        }
+
+        try {
+            ctrl.createMock("myMock", List.class, args, methods);
+            fail("partial mocking on interface shouln't be allowed");
+        } catch (final IllegalArgumentException e) {
+        }
+    }
+
+    private void testList(final IMocksControl ctrl, final List<?> list) {
+        expect(list.size()).andReturn(3);
+        ctrl.replay();
+        assertEquals(3, list.size());
+        ctrl.verify();
+    }
+
+    @Test
+    @Deprecated
+    public void testCreateOldMockTypeFromNewMockType() {
+        assertSame(MockType.NICE, MocksControl.MockType.NICE.realType);
+    }
+
+    @Test
+    public void testCreateMocksControlFromOldMockType() {
+        MocksControl c = new MocksControl(MocksControl.MockType.NICE);
+        assertSame(MockType.NICE, c.getType());
+    }
+}
diff --git a/tests/org/easymock/tests2/NameTest.java b/tests/org/easymock/tests2/NameTest.java
index 917ee00..b225b15 100644
--- a/tests/org/easymock/tests2/NameTest.java
+++ b/tests/org/easymock/tests2/NameTest.java
@@ -1,75 +1,96 @@
-package org.easymock.tests2;
-
-import org.easymock.IMocksControl;
-import org.easymock.tests.IMethods;
-import org.junit.Test;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-public class NameTest {
-    @Test
-    public void nameForMock() {
-        IMethods mock = createMock("mock", IMethods.class);
-        mock.simpleMethod();
-        replay(mock);
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            String actualMessage = expected.getMessage();
-            String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
-            assertEquals(expectedMessage, actualMessage);         
-        }
-    }
-    @Test
-    public void nameForStrictMock() {
-        IMethods mock = createStrictMock("mock", IMethods.class);
-        mock.simpleMethod();
-        replay(mock);
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            String actualMessage = expected.getMessage();
-            String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
-            assertEquals(expectedMessage, actualMessage);         
-        }
-    }
-    @Test
-    public void nameForNiceMock() {
-        IMethods mock = createNiceMock("mock", IMethods.class);
-        mock.simpleMethod();
-        replay(mock);
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            String actualMessage = expected.getMessage();
-            String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
-            assertEquals(expectedMessage, actualMessage);         
-        }
-    }
-    @Test
-    public void nameForMocksControl() {
-        IMocksControl control = createControl();
-        IMethods mock = control.createMock("mock", IMethods.class);
-        mock.simpleMethod();
-        replay(mock);
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            String actualMessage = expected.getMessage();
-            String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
-            assertEquals(expectedMessage, actualMessage);         
-        }
-    }
-    
-    @Test
-    public void shouldThrowIllegalArgumentExceptionIfNameIsNoValidJavaIdentifier() {
-        try {
-            createMock("no-valid-java-identifier", IMethods.class);
-            throw new AssertionError();
-        } catch (IllegalArgumentException expected) {
-            assertEquals("'no-valid-java-identifier' is not a valid Java identifier.", expected.getMessage());
-        }
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.IMocksControl;
+import org.easymock.tests.IMethods;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class NameTest {
+    @Test
+    public void nameForMock() {
+        final IMethods mock = createMock("mock", IMethods.class);
+        mock.simpleMethod();
+        replay(mock);
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            final String actualMessage = expected.getMessage();
+            final String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
+            assertEquals(expectedMessage, actualMessage);
+        }
+    }
+
+    @Test
+    public void nameForStrictMock() {
+        final IMethods mock = createStrictMock("mock", IMethods.class);
+        mock.simpleMethod();
+        replay(mock);
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            final String actualMessage = expected.getMessage();
+            final String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
+            assertEquals(expectedMessage, actualMessage);
+        }
+    }
+
+    @Test
+    public void nameForNiceMock() {
+        final IMethods mock = createNiceMock("mock", IMethods.class);
+        mock.simpleMethod();
+        replay(mock);
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            final String actualMessage = expected.getMessage();
+            final String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
+            assertEquals(expectedMessage, actualMessage);
+        }
+    }
+
+    @Test
+    public void nameForMocksControl() {
+        final IMocksControl control = createControl();
+        final IMethods mock = control.createMock("mock", IMethods.class);
+        mock.simpleMethod();
+        replay(mock);
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            final String actualMessage = expected.getMessage();
+            final String expectedMessage = "\n  Expectation failure on verify:\n    mock.simpleMethod(): expected: 1, actual: 0";
+            assertEquals(expectedMessage, actualMessage);
+        }
+    }
+
+    @Test
+    public void shouldThrowIllegalArgumentExceptionIfNameIsNoValidJavaIdentifier() {
+        try {
+            createMock("no-valid-java-identifier", IMethods.class);
+            throw new AssertionError();
+        } catch (final IllegalArgumentException expected) {
+            assertEquals("'no-valid-java-identifier' is not a valid Java identifier.", expected.getMessage());
+        }
+    }
+
+}
diff --git a/tests/org/easymock/tests2/NiceMockTest.java b/tests/org/easymock/tests2/NiceMockTest.java
index 0bcd1ce..3581232 100644
--- a/tests/org/easymock/tests2/NiceMockTest.java
+++ b/tests/org/easymock/tests2/NiceMockTest.java
@@ -1,47 +1,61 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class NiceMockTest {
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        mock = createNiceMock(IMethods.class);
-        replay(mock);
-    }
-
-    @Test
-    public void defaultReturnValueBoolean() {
-        assertEquals(false, mock.booleanReturningMethod(12));
-        verify(mock);
-    }
-
-    @Test
-    public void defaultReturnValueFloat() {
-        assertEquals(0.0f, mock.floatReturningMethod(12), 0.0f);
-        verify(mock);
-    }
-
-    @Test
-    public void defaultReturnValueDouble() {
-        assertEquals(0.0d, mock.doubleReturningMethod(12), 0.0d);
-        verify(mock);
-    }
-
-    @Test
-    public void defaultReturnValueObject() {
-        assertEquals(null, mock.objectReturningMethod(12));
-        verify(mock);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class NiceMockTest {
+
+    IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createNiceMock(IMethods.class);
+        replay(mock);
+    }
+
+    @Test
+    public void defaultReturnValueBoolean() {
+        assertEquals(false, mock.booleanReturningMethod(12));
+        verify(mock);
+    }
+
+    @Test
+    public void defaultReturnValueFloat() {
+        assertEquals(0.0f, mock.floatReturningMethod(12), 0.0f);
+        verify(mock);
+    }
+
+    @Test
+    public void defaultReturnValueDouble() {
+        assertEquals(0.0d, mock.doubleReturningMethod(12), 0.0d);
+        verify(mock);
+    }
+
+    @Test
+    public void defaultReturnValueObject() {
+        assertEquals(null, mock.objectReturningMethod(12));
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests2/ParentEquals.java b/tests/org/easymock/tests2/ParentEquals.java
new file mode 100644
index 0000000..b255a14
--- /dev/null
+++ b/tests/org/easymock/tests2/ParentEquals.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+/**
+ * @author Henri Tremblay
+ */
+class ParentEquals {
+    public boolean equals(Object o) {
+        return super.equals(o);
+    }
+}
diff --git a/tests/org/easymock/tests2/PartialMockingTest.java b/tests/org/easymock/tests2/PartialMockingTest.java
new file mode 100644
index 0000000..5525aa5
--- /dev/null
+++ b/tests/org/easymock/tests2/PartialMockingTest.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+
+import org.easymock.ConstructorArgs;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class PartialMockingTest {
+
+    public static abstract class A {
+
+        public String s;
+
+        public int i;
+
+        protected A(final String s) {
+            this.s = s;
+        }
+
+        private A(final int i) {
+            this.i = i;
+        }
+
+        protected abstract int foo();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testPartialMock_PublicConstructor() throws Exception {
+        final ArrayList<String> list = createMockBuilder(ArrayList.class).withConstructor(3).createMock();
+        list.add("test"); // shouldn't crash since constructor was called
+    }
+
+    @Test
+    public void testPartialMock_ProtectedConstructor() throws Exception {
+        final A a = createMockBuilder(A.class).withConstructor("test").createMock();
+        assertEquals("test", a.s); // make sure constructor was called
+
+        // Check that abstract method is mocked by default
+        expect(a.foo()).andReturn(3);
+        replay(a);
+        assertEquals(3, a.foo());
+        verify(a);
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void testPartialMock_ConstructorNotFound() throws Exception {
+        final Constructor<?> cstr = ArrayList.class.getConstructor(Integer.TYPE);
+        final ConstructorArgs constructorArgs = new ConstructorArgs(cstr, 2.0);
+        try {
+            createMockBuilder(ArrayList.class).withConstructor(Integer.TYPE).withArgs(2.0).createMock();
+        } catch (final RuntimeException e) {
+            assertEquals("Failed to find constructor for param types", e.getMessage());
+            throw e;
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testPartialMock_InvalidParams() throws Exception {
+        final Constructor<?> cstr = ArrayList.class.getConstructor(Integer.TYPE);
+        final ConstructorArgs constructorArgs = new ConstructorArgs(cstr, "test");
+        createMockBuilder(ArrayList.class).withConstructor(Integer.TYPE).withArgs("test");
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void testPartialMock_ExceptionInConstructor() throws Exception {
+        final Constructor<?> cstr = ArrayList.class.getConstructor(Integer.TYPE);
+        final ConstructorArgs constructorArgs = new ConstructorArgs(cstr, -5);
+        createMockBuilder(ArrayList.class).withConstructor(-5).createMock();
+    }
+}
diff --git a/tests/org/easymock/tests2/ReflectionUtilsTest.java b/tests/org/easymock/tests2/ReflectionUtilsTest.java
new file mode 100644
index 0000000..b455fd7
--- /dev/null
+++ b/tests/org/easymock/tests2/ReflectionUtilsTest.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.easymock.internal.ReflectionUtils;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class ReflectionUtilsTest {
+
+    public static class B {
+        protected void foo(final long l) {
+        }
+    }
+
+    public static class A extends B {
+
+        public A(final boolean bool, final byte b, final int i, final short s, final char c, final long l,
+                final float f, final double d) {
+        }
+
+        public A(final int i) {
+        }
+
+        protected A(final long l) {
+        }
+
+        private A(final byte b) {
+        }
+
+        A(final char c) {
+        }
+
+        public A(final CharSequence c) {
+        }
+
+        public A(final StringBuilder s) {
+        }
+
+        public void foo(final String s) {
+        }
+
+        public void foo(final int i) {
+        }
+    }
+
+    @Test
+    public void testFindMethod() {
+        final Method m = ReflectionUtils.findMethod(String.class, "length");
+        assertEquals(String.class, m.getDeclaringClass());
+        assertEquals("length", m.getName());
+        assertEquals(int.class, m.getReturnType());
+    }
+
+    @Test
+    public void testFindMethod_NotFound() {
+        final Method m = ReflectionUtils.findMethod(String.class, "aaa");
+        assertNull(m);
+    }
+
+    @Test
+    public void testFindMethod_Ambiguous() {
+        try {
+            ReflectionUtils.findMethod(A.class, "foo");
+        } catch (final RuntimeException e) {
+            assertEquals("Ambiguous name: More than one method are named foo", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testFindMethod_WrongParams() {
+        final Method m = ReflectionUtils.findMethod(A.class, "foo", int.class, int.class);
+        assertNull(m);
+    }
+
+    @Test
+    public void testFindMethod_Superclass() {
+        final Method m = ReflectionUtils.findMethod(A.class, "foo", long.class);
+        assertEquals("protected void " + B.class.getName() + ".foo(long)", m.toString());
+    }
+
+    @Test
+    public void testFindMethodClassOfQStringClassOfQArray() {
+        final Method m = ReflectionUtils.findMethod(A.class, "foo", int.class);
+        assertEquals("public void " + A.class.getName() + ".foo(int)", m.toString());
+    }
+
+    @Test
+    public void testGetConstructor_public() throws NoSuchMethodException {
+        final Constructor<A> c = ReflectionUtils.getConstructor(A.class, 5);
+        assertArrayEquals(new Class[] { int.class }, c.getParameterTypes());
+    }
+
+    @Test
+    public void testGetConstructor_protected() throws NoSuchMethodException {
+        final Constructor<A> c = ReflectionUtils.getConstructor(A.class, 5l);
+        assertArrayEquals(new Class[] { long.class }, c.getParameterTypes());
+    }
+
+    @Test
+    public void testGetConstructor_default() throws NoSuchMethodException {
+        final Constructor<A> c = ReflectionUtils.getConstructor(A.class, 'c');
+        assertArrayEquals(new Class[] { char.class }, c.getParameterTypes());
+    }
+
+    @Test(expected = NoSuchMethodException.class)
+    public void testGetConstructor_private() throws NoSuchMethodException {
+        ReflectionUtils.getConstructor(A.class, (byte) 5);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGetConstructor_twoMatching() throws NoSuchMethodException {
+        ReflectionUtils.getConstructor(A.class, new StringBuilder());
+    }
+
+    @Test(expected = NoSuchMethodException.class)
+    public void testGetConstructor_notFound() throws NoSuchMethodException {
+        ReflectionUtils.getConstructor(A.class, true);
+    }
+
+    @Test(expected = NoSuchMethodException.class)
+    public void testGetConstructor_WrongParams() throws NoSuchMethodException {
+        ReflectionUtils.getConstructor(A.class, "", "");
+    }
+
+    @Test
+    public void testGetConstructor_AllPrimitives() throws NoSuchMethodException {
+        final Constructor<A> c = ReflectionUtils.getConstructor(A.class, true, (byte) 1, 2, (short) 3, 'g',
+                5l, 4.0f, 8.0);
+        assertNotNull(c);
+    }
+
+    @Test
+    public void testGetDeclareMethod_Found() throws Exception {
+        final Method expected = A.class.getDeclaredMethod("foo", new Class<?>[] { int.class });
+        final Method actual = ReflectionUtils.getDeclaredMethod(A.class, "foo", new Class<?>[] { int.class });
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testGetDeclareMethod_NotFound() {
+        try {
+            ReflectionUtils.getDeclaredMethod(A.class, "foo", new Class<?>[0]);
+            fail("Method should not be found");
+        } catch (final RuntimeException e) {
+            assertTrue(e.getCause() instanceof NoSuchMethodException);
+        }
+    }
+}
diff --git a/tests/org/easymock/tests2/SerializationTest.java b/tests/org/easymock/tests2/SerializationTest.java
index 99ed23c..26c53df 100644
--- a/tests/org/easymock/tests2/SerializationTest.java
+++ b/tests/org/easymock/tests2/SerializationTest.java
@@ -1,49 +1,125 @@
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.util.List;
-
-import org.junit.Test;
-
-public class SerializationTest {
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void test() throws Exception {
-        List<String> mock = createMock(List.class);
-        
-        mock = serialize(mock);
-        
-        expect(mock.get(1)).andReturn("a");
-        
-        mock = serialize(mock);
-        
-        replay(mock);
-        
-        mock = serialize(mock);
-        
-        assertEquals("a", mock.get(1));
-        
-        mock = serialize(mock);
-        
-        verify(mock);
-    }
-
-    @SuppressWarnings("unchecked")
-    private <T> T serialize(T o) throws IOException, ClassNotFoundException {
-        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
-        ObjectOutputStream out = new ObjectOutputStream(bOut);
-        out.writeObject(o);
-        out.close();
-        
-        ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
-        ObjectInputStream in = new ObjectInputStream(bIn);
-        o = (T) in.readObject();
-        in.close();
-        
-        return o;
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Henri Tremblay
+ */
+public class SerializationTest implements Serializable {
+
+    private static final long serialVersionUID = -774994679161263654L;
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void test() throws Exception {
+
+        List<String> mock = createMock(List.class);
+
+        mock = serialize(mock);
+
+        expect(mock.get(1)).andReturn("a");
+
+        mock = serialize(mock);
+
+        replay(mock);
+
+        mock = serialize(mock);
+
+        assertEquals("a", mock.get(1));
+
+        mock = serialize(mock);
+
+        verify(mock);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testClass() throws Exception {
+
+        ArrayList<String> mock = createMockBuilder(ArrayList.class).addMockedMethod("get").withConstructor()
+                .createMock();
+
+        mock = serialize(mock);
+
+        expect(mock.get(1)).andReturn("a");
+
+        mock = serialize(mock);
+
+        replay(mock);
+
+        mock = serialize(mock);
+
+        assertEquals("a", mock.get(1));
+
+        mock = serialize(mock);
+
+        verify(mock);
+    }
+
+    @Test
+    public void testAllMockedMethod() throws Exception {
+
+        SerializationTest mock = createMock(SerializationTest.class);
+
+        mock = serialize(mock);
+
+        mock.test();
+
+        mock = serialize(mock);
+
+        replay(mock);
+
+        mock = serialize(mock);
+
+        mock.test();
+
+        mock = serialize(mock);
+
+        verify(mock);
+    }
+
+    @Test
+    @Ignore
+    // to code one day to make sure we can recreate a mock in another class loader
+    public void testChangingClassLoader() {
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private <T> T serialize(T o) throws IOException, ClassNotFoundException {
+        final ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+        final ObjectOutputStream out = new ObjectOutputStream(bOut);
+        out.writeObject(o);
+        out.close();
+
+        final ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray());
+        final ObjectInputStream in = new ObjectInputStream(bIn);
+        o = (T) in.readObject();
+        in.close();
+
+        return o;
+    }
+}
diff --git a/tests/org/easymock/tests2/StubTest.java b/tests/org/easymock/tests2/StubTest.java
index 450cf6a..6ecc26c 100644
--- a/tests/org/easymock/tests2/StubTest.java
+++ b/tests/org/easymock/tests2/StubTest.java
@@ -1,72 +1,86 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class StubTest {
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        mock = createStrictMock(IMethods.class);
-    }
-
-    @Test
-    public void stub() {
-        mock.simpleMethodWithArgument("1");
-        expectLastCall().anyTimes();
-        mock.simpleMethodWithArgument("2");
-        expectLastCall().anyTimes();
-        mock.simpleMethodWithArgument("3");
-        expectLastCall().asStub();
-
-        replay(mock);
-
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("3");
-
-        verify(mock);
-
-    }
-
-    @Test
-    public void stubWithReturnValue() {
-        expect(mock.oneArg("1")).andReturn("A").andStubReturn("B");
-        expect(mock.oneArg("2")).andThrow(new IllegalArgumentException())
-                .andStubThrow(new IllegalStateException());
-
-        replay(mock);
-
-        assertEquals("A", mock.oneArg("1"));
-        assertEquals("B", mock.oneArg("1"));
-        assertEquals("B", mock.oneArg("1"));
-        try {
-            mock.oneArg("2");
-        } catch (IllegalArgumentException ignored) {
-        }
-        assertEquals("B", mock.oneArg("1"));
-        try {
-            mock.oneArg("2");
-        } catch (IllegalStateException ignored) {
-        }
-        assertEquals("B", mock.oneArg("1"));
-        try {
-            mock.oneArg("2");
-        } catch (IllegalStateException ignored) {
-        }
-        verify(mock);
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class StubTest {
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createStrictMock(IMethods.class);
+    }
+
+    @Test
+    public void stub() {
+        mock.simpleMethodWithArgument("1");
+        expectLastCall().anyTimes();
+        mock.simpleMethodWithArgument("2");
+        expectLastCall().anyTimes();
+        mock.simpleMethodWithArgument("3");
+        expectLastCall().asStub();
+
+        replay(mock);
+
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("3");
+
+        verify(mock);
+
+    }
+
+    @Test
+    public void stubWithReturnValue() {
+        expect(mock.oneArg("1")).andReturn("A").andStubReturn("B");
+        expect(mock.oneArg("2")).andThrow(new IllegalArgumentException()).andStubThrow(
+                new IllegalStateException());
+
+        replay(mock);
+
+        assertEquals("A", mock.oneArg("1"));
+        assertEquals("B", mock.oneArg("1"));
+        assertEquals("B", mock.oneArg("1"));
+        try {
+            mock.oneArg("2");
+        } catch (final IllegalArgumentException ignored) {
+        }
+        assertEquals("B", mock.oneArg("1"));
+        try {
+            mock.oneArg("2");
+        } catch (final IllegalStateException ignored) {
+        }
+        assertEquals("B", mock.oneArg("1"));
+        try {
+            mock.oneArg("2");
+        } catch (final IllegalStateException ignored) {
+        }
+        verify(mock);
+    }
+
+}
diff --git a/tests/org/easymock/tests2/ThreadingTest.java b/tests/org/easymock/tests2/ThreadingTest.java
index 21348d9..965c924 100644
--- a/tests/org/easymock/tests2/ThreadingTest.java
+++ b/tests/org/easymock/tests2/ThreadingTest.java
@@ -1,91 +1,204 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Henri Tremblay.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.*;
-
-import org.easymock.tests.IMethods;
-import org.junit.Test;
-
-/**
- * Test that EasyMock works in replay state in a multithreaded
- * environment. Note that sadly this test isn't sure to fail all
- * the time. Only if there's a concurrency issue and we're lucky
- * enough to fell on it during testing.
- */
-public class ThreadingTest {
-
-    private static final int THREAD_COUNT = 10;
-
-    @Test
-    public void testThreadSafe() throws Throwable {
-
-        final IMethods mock = createMock(IMethods.class);
-        expect(mock.oneArg("test")).andReturn("result").times(THREAD_COUNT);
-        
-        makeThreadSafe(mock, true);
-        
-        replay(mock);
-        
-        Callable<String> replay = new Callable<String>() {
-            public String call() throws Exception {
-                return mock.oneArg("test");
-            }
-        };
-        
-        ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
-
-        List<Callable<String>> tasks = Collections.nCopies(THREAD_COUNT, replay);
-
-        List<Future<String>> results = service.invokeAll(tasks);
-
-        for (Future<String> future : results) {
-            assertEquals("result", future.get());
-        }
-
-        verify(mock);
-    }
-    
-    @Test
-    public void testThreadNotSafe() throws Throwable {
-
-        final IMethods mock = createMock(IMethods.class);
-        expect(mock.oneArg("test")).andReturn("result").times(THREAD_COUNT);
-        
-        replay(mock);
-        
-        Callable<String> replay = new Callable<String>() {
-            public String call() throws Exception {
-                return mock.oneArg("test");
-            }
-        };
-        
-        ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
-
-        List<Callable<String>> tasks = Collections.nCopies(THREAD_COUNT, replay);
-
-        List<Future<String>> results = service.invokeAll(tasks);
-        
-        boolean exceptionThrown = false;
-
-        for (Future<String> future : results) {
-            try {
-                assertEquals("result", future.get());
-            }
-            catch(ExecutionException e) {
-                assertEquals("\n  Un-thread-safe mock called from multiple threads", e.getCause().getMessage());
-                exceptionThrown = true;
-            }
-        }
-        
-        assertTrue(exceptionThrown);
-    }    
-}
-
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.*;
+
+import org.easymock.internal.AssertionErrorWrapper;
+import org.easymock.internal.MocksBehavior;
+import org.easymock.tests.IMethods;
+import org.junit.Test;
+
+/**
+ * Test that EasyMock works in replay state in a multithreaded environment. Note
+ * that sadly this test isn't sure to fail all the time. Only if there's a
+ * concurrency issue and we're lucky enough to fell on it during testing.
+ * 
+ * @author Henri Tremblay
+ */
+public class ThreadingTest {
+
+    private static final int THREAD_COUNT = 10;
+
+    @Test
+    public void testThreadSafe() throws Throwable {
+
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg("test")).andReturn("result").times(THREAD_COUNT);
+
+        replay(mock);
+
+        final Callable<String> replay = new Callable<String>() {
+            public String call() throws Exception {
+                return mock.oneArg("test");
+            }
+        };
+
+        final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
+
+        final List<Callable<String>> tasks = Collections.nCopies(THREAD_COUNT, replay);
+
+        final List<Future<String>> results = service.invokeAll(tasks);
+
+        for (final Future<String> future : results) {
+            assertEquals("result", future.get());
+        }
+
+        verify(mock);
+    }
+
+    @Test
+    public void testThreadNotSafe() throws Throwable {
+
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg("test")).andReturn("result").times(THREAD_COUNT);
+
+        makeThreadSafe(mock, false);
+
+        checkIsUsedInOneThread(mock, true);
+
+        replay(mock);
+
+        final Callable<String> replay = new Callable<String>() {
+            public String call() throws Exception {
+                return mock.oneArg("test");
+            }
+        };
+
+        final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
+
+        final List<Callable<String>> tasks = Collections.nCopies(THREAD_COUNT, replay);
+
+        final List<Future<String>> results = service.invokeAll(tasks);
+
+        boolean exceptionThrown = false;
+
+        for (final Future<String> future : results) {
+            try {
+                assertEquals("result", future.get());
+            } catch (final ExecutionException e) {
+                // Since I don't know which one the lastThread is, that's the
+                // best assert I can do except doing
+                // a regular exception and I don't think it worth it
+                assertTrue(e.getCause().getMessage().startsWith(
+                        "\n Mock isn't supposed to be called from multiple threads. Last: "));
+                exceptionThrown = true;
+            }
+        }
+
+        assertTrue(exceptionThrown);
+    }
+
+    @Test
+    public void testMockUsedCorrectly() {
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg("test")).andReturn("result").times(2);
+
+        checkIsUsedInOneThread(mock, true);
+
+        replay(mock);
+
+        mock.oneArg("test");
+        mock.oneArg("test");
+
+        verify(mock);
+    }
+
+    @Test
+    public void testChangeDefault() throws Throwable {
+        final String previousThreadSafetyCheck = setEasyMockProperty(ENABLE_THREAD_SAFETY_CHECK_BY_DEFAULT,
+                Boolean.TRUE.toString());
+        final String previousThreadSafe = setEasyMockProperty(NOT_THREAD_SAFE_BY_DEFAULT, Boolean.TRUE
+                .toString());
+        try {
+            final MocksBehavior behavior = new MocksBehavior(true);
+            assertFalse(behavior.isThreadSafe());
+
+            final Thread t = new Thread() {
+                @Override
+                public void run() {
+                    behavior.checkThreadSafety();
+                }
+            };
+            t.start();
+            t.join();
+            try {
+                behavior.checkThreadSafety();
+                fail("Shouldn't work");
+            } catch (final AssertionErrorWrapper e) {
+
+            }
+
+        } finally {
+            setEasyMockProperty(ENABLE_THREAD_SAFETY_CHECK_BY_DEFAULT, previousThreadSafetyCheck);
+            setEasyMockProperty(NOT_THREAD_SAFE_BY_DEFAULT, previousThreadSafe);
+        }
+    }
+
+    @Test
+    public void testRecordingInMultipleThreads() throws InterruptedException, ExecutionException {
+
+        final Callable<String> replay = new Callable<String>() {
+            public String call() throws Exception {
+                final IMethods mock = createMock(IMethods.class);
+                expect(mock.oneArg("test")).andReturn("result");
+
+                replay(mock);
+
+                final String s = mock.oneArg("test");
+
+                verify(mock);
+
+                return s;
+            }
+        };
+
+        final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
+
+        final List<Callable<String>> tasks = Collections.nCopies(THREAD_COUNT, replay);
+
+        final List<Future<String>> results = service.invokeAll(tasks);
+
+        for (final Future<String> future : results) {
+            assertEquals("result", future.get());
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testCleanupAfterFailureInRecordPhase() {
+        Comparable<String> mock = createNiceMock(Comparable.class);
+
+        // Mocking equals() doesn't work
+        try {
+            expect(mock.equals(eq(mock))).andReturn(true);
+        } catch (final IllegalStateException e) {
+
+        }
+
+        // However, the recorded matchers should be cleaned to prevent impacting
+        // other tests
+        mock = createNiceMock(Comparable.class);
+        expect(mock.compareTo((String) isNull())).andReturn(1);
+        replay(mock);
+        assertEquals(1, mock.compareTo(null));
+    }
+}
diff --git a/tests/org/easymock/tests2/UsageConstraintsTest.java b/tests/org/easymock/tests2/UsageConstraintsTest.java
index cb90768..961e90f 100644
--- a/tests/org/easymock/tests2/UsageConstraintsTest.java
+++ b/tests/org/easymock/tests2/UsageConstraintsTest.java
@@ -1,641 +1,653 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import java.math.BigDecimal;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.easymock.EasyMock;
-import org.easymock.LogicalOperator;
-import org.easymock.internal.matchers.Equals;
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class UsageConstraintsTest {
-    private IMethods mock;
-
-    @Before
-    public void setUp() {
-        mock = createMock(IMethods.class);
-    }
-
-    @Test
-    public void equalsMissing() {
-        mock.simpleMethodWithArgument(not(eq("asd")));
-        try {
-            mock.simpleMethodWithArgument(not("jkl"));
-            fail();
-        } catch (IllegalStateException e) {
-            assertEquals("no matchers found.", e.getMessage());
-        }
-        try {
-            mock.simpleMethodWithArgument(or(eq("jkl"), "asd"));
-            fail();
-        } catch (IllegalStateException e) {
-            assertEquals("2 matchers expected, 1 recorded.", e.getMessage());
-        }
-        try {
-            mock.threeArgumentMethod(1, "asd", eq("asd"));
-            fail();
-        } catch (IllegalStateException e) {
-            assertEquals("3 matchers expected, 1 recorded.", e.getMessage());
-        }
-
-    }
-
-    @Test
-    public void differentConstraintsOnSameCall() {
-        mock.simpleMethodWithArgument((String) isNull());
-        mock.simpleMethodWithArgument((String) notNull());
-        replay(mock);
-        mock.simpleMethodWithArgument(null);
-        mock.simpleMethodWithArgument("2");
-    }
-
-    @Test
-    public void equals() {
-        assertEquals(new Equals(null), new Equals(null));
-        assertEquals(new Equals(new Integer(2)), new Equals(new Integer(2)));
-        assertFalse(new Equals(null).equals(null));
-        assertFalse(new Equals(null).equals("Test"));
-        try {
-            new Equals(null).hashCode();
-            fail();
-        } catch (UnsupportedOperationException expected) {
-        }
-    }
-
-    @Test
-    public void constraints() {
-        expect(
-                mock.threeArgumentMethod(and(geq(7), leq(10)),
-                        isA(String.class), contains("123"))).andReturn("456")
-                .atLeastOnce();
-        replay(mock);
-        boolean failed = false;
-        try {
-            mock.threeArgumentMethod(11, "", "01234");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail();
-        }
-        failed = false;
-        try {
-            mock.threeArgumentMethod(8, new Object(), "01234");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail();
-        }
-        failed = false;
-        try {
-            mock.threeArgumentMethod(8, "", "no match");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail();
-        }
-        assertEquals("456", mock.threeArgumentMethod(8, "", "01234"));
-        verify(mock);
-    }
-
-    @Test
-    public void andOverloaded() {
-        expect(mock.oneArg(and(eq(false), eq(false)))).andReturn("0");
-        expect(mock.oneArg(and(eq((byte) 1), eq((byte) 1)))).andReturn("1");
-        expect(mock.oneArg(and(eq('a'), eq('a')))).andReturn("2");
-        expect(mock.oneArg(and(eq((double) 1), eq((double) 1)))).andReturn("3");
-        expect(mock.oneArg(and(eq((float) 1), eq((float) 1)))).andReturn("4");
-        expect(mock.oneArg(and(eq((int) 1), eq((int) 1)))).andReturn("5");
-        expect(mock.oneArg(and(eq((long) 1), eq((long) 1)))).andReturn("6");
-        expect(mock.oneArg(and(eq((short) 1), eq((short) 1)))).andReturn("7");
-        expect(mock.oneArg(and(contains("a"), contains("d")))).andReturn("8");
-        expect(mock.oneArg(and(isA(Class.class), eq(Object.class)))).andReturn(
-                "9");
-        replay(mock);
-        assertEquals("9", mock.oneArg(Object.class));
-        assertEquals("0", mock.oneArg(false));
-        assertEquals("1", mock.oneArg((byte) 1));
-        assertEquals("2", mock.oneArg('a'));
-        assertEquals("3", mock.oneArg((double) 1));
-        assertEquals("7", mock.oneArg((short) 1));
-        assertEquals("8", mock.oneArg("abcde"));
-        assertEquals("4", mock.oneArg((float) 1));
-        assertEquals("5", mock.oneArg((int) 1));
-        assertEquals("6", mock.oneArg((long) 1));
-        verify(mock);
-    }
-
-    @Test
-    public void orOverloaded() {
-        expect(mock.oneArg(or(eq(false), eq(true)))).andReturn("0");
-        expect(mock.oneArg(or(eq((byte) 1), eq((byte) 2)))).andReturn("1");
-        expect(mock.oneArg(or(eq((char) 1), eq((char) 2)))).andReturn("2");
-        expect(mock.oneArg(or(eq((double) 1), eq((double) 2)))).andReturn("3");
-        expect(mock.oneArg(or(eq((float) 1), eq((float) 2)))).andReturn("4");
-        expect(mock.oneArg(or(eq((int) 1), eq((int) 2)))).andReturn("5");
-        expect(mock.oneArg(or(eq((long) 1), eq((long) 2)))).andReturn("6");
-        expect(mock.oneArg(or(eq((short) 1), eq((short) 2)))).andReturn("7");
-        expect(mock.oneArg(or(eq("asd"), eq("jkl")))).andReturn("8");
-        expect(mock.oneArg(or(eq(this.getClass()), eq(Object.class))))
-                .andReturn("9");
-        replay(mock);
-        assertEquals("9", mock.oneArg(Object.class));
-        assertEquals("0", mock.oneArg(true));
-        assertEquals("1", mock.oneArg((byte) 2));
-        assertEquals("2", mock.oneArg((char) 1));
-        assertEquals("3", mock.oneArg((double) 2));
-        assertEquals("7", mock.oneArg((short) 1));
-        assertEquals("8", mock.oneArg("jkl"));
-        assertEquals("4", mock.oneArg((float) 1));
-        assertEquals("5", mock.oneArg((int) 2));
-        assertEquals("6", mock.oneArg((long) 1));
-        verify(mock);
-    }
-
-    @Test
-    public void notOverloaded() {
-        expect(mock.oneArg(not(eq(false)))).andReturn("0");
-        expect(mock.oneArg(not(eq((byte) 1)))).andReturn("1");
-        expect(mock.oneArg(not(eq('a')))).andReturn("2");
-        expect(mock.oneArg(not(eq((double) 1)))).andReturn("3");
-        expect(mock.oneArg(not(eq((float) 1)))).andReturn("4");
-        expect(mock.oneArg(not(eq((int) 1)))).andReturn("5");
-        expect(mock.oneArg(not(eq((long) 1)))).andReturn("6");
-        expect(mock.oneArg(not(eq((short) 1)))).andReturn("7");
-        expect(mock.oneArg(not(contains("a")))).andReturn("8");
-        expect(mock.oneArg(not(isA(Class.class)))).andReturn("9");
-        replay(mock);
-        assertEquals("9", mock.oneArg(new Object()));
-        assertEquals("0", mock.oneArg(true));
-        assertEquals("1", mock.oneArg((byte) 2));
-        assertEquals("2", mock.oneArg('b'));
-        assertEquals("3", mock.oneArg((double) 2));
-        assertEquals("7", mock.oneArg((short) 2));
-        assertEquals("8", mock.oneArg("bcde"));
-        assertEquals("4", mock.oneArg((float) 2));
-        assertEquals("5", mock.oneArg((int) 2));
-        assertEquals("6", mock.oneArg((long) 2));
-        verify(mock);
-    }
-
-    @Test
-    public void lessOrEqualOverloaded() {
-        expect(mock.oneArg(leq((byte) 1))).andReturn("1");
-        expect(mock.oneArg(leq((double) 1))).andReturn("3");
-        expect(mock.oneArg(leq((float) 1))).andReturn("4");
-        expect(mock.oneArg(leq((int) 1))).andReturn("5");
-        expect(mock.oneArg(leq((long) 1))).andReturn("6");
-        expect(mock.oneArg(leq((short) 1))).andReturn("7");
-        expect(mock.oneArg(leq(new BigDecimal("1")))).andReturn("8");
-        replay(mock);
-        assertEquals("1", mock.oneArg((byte) 1));
-        assertEquals("3", mock.oneArg((double) 1));
-        assertEquals("7", mock.oneArg((short) 0));
-        assertEquals("4", mock.oneArg((float) -5));
-        assertEquals("5", mock.oneArg((int) -2));
-        assertEquals("6", mock.oneArg((long) -3));
-        assertEquals("8", mock.oneArg(new BigDecimal("0.5")));
-        verify(mock);
-    }
-
-    @Test
-    public void lessThanOverloaded() {
-        expect(mock.oneArg(lt((byte) 1))).andReturn("1");
-        expect(mock.oneArg(lt((double) 1))).andReturn("3");
-        expect(mock.oneArg(lt((float) 1))).andReturn("4");
-        expect(mock.oneArg(lt((int) 1))).andReturn("5");
-        expect(mock.oneArg(lt((long) 1))).andReturn("6");
-        expect(mock.oneArg(lt((short) 1))).andReturn("7");
-        expect(mock.oneArg(lt(new BigDecimal("1")))).andReturn("8");
-        replay(mock);
-        assertEquals("1", mock.oneArg((byte) 0));
-        assertEquals("3", mock.oneArg((double) 0));
-        assertEquals("7", mock.oneArg((short) 0));
-        assertEquals("4", mock.oneArg((float) -4));
-        assertEquals("5", mock.oneArg((int) -34));
-        assertEquals("6", mock.oneArg((long) -6));
-        assertEquals("8", mock.oneArg(new BigDecimal("0.5")));
-        verify(mock);
-    }
-
-    @Test
-    public void greaterOrEqualOverloaded() {
-        expect(mock.oneArg(geq((byte) 1))).andReturn("1");
-        expect(mock.oneArg(geq((double) 1))).andReturn("3");
-        expect(mock.oneArg(geq((float) 1))).andReturn("4");
-        expect(mock.oneArg(geq((int) 1))).andReturn("5");
-        expect(mock.oneArg(geq((long) 1))).andReturn("6");
-        expect(mock.oneArg(geq((short) 1))).andReturn("7");
-        expect(mock.oneArg(geq(new BigDecimal("1")))).andReturn("8");
-        replay(mock);
-        assertEquals("1", mock.oneArg((byte) 2));
-        assertEquals("3", mock.oneArg((double) 1));
-        assertEquals("7", mock.oneArg((short) 2));
-        assertEquals("4", mock.oneArg((float) 3));
-        assertEquals("5", mock.oneArg((int) 4));
-        assertEquals("6", mock.oneArg((long) 5));
-        assertEquals("8", mock.oneArg(new BigDecimal("1.5")));
-        verify(mock);
-    }
-
-    @Test
-    public void greaterThanOverloaded() {
-        expect(mock.oneArg(gt((byte) 1))).andReturn("1");
-        expect(mock.oneArg(gt((double) 1))).andReturn("3");
-        expect(mock.oneArg(gt((float) 1))).andReturn("4");
-        expect(mock.oneArg(gt((int) 1))).andReturn("5");
-        expect(mock.oneArg(gt((long) 1))).andReturn("6");
-        expect(mock.oneArg(gt((short) 1))).andReturn("7");
-        expect(mock.oneArg(gt(new BigDecimal("1")))).andReturn("8");
-        replay(mock);
-        assertEquals("1", mock.oneArg((byte) 2));
-        assertEquals("3", mock.oneArg((double) 2));
-        assertEquals("7", mock.oneArg((short) 2));
-        assertEquals("4", mock.oneArg((float) 3));
-        assertEquals("5", mock.oneArg((int) 2));
-        assertEquals("6", mock.oneArg((long) 5));
-        assertEquals("8", mock.oneArg(new BigDecimal("1.5")));
-        verify(mock);
-    }
-
-    @Test
-    public void cmpTo() {
-        expect(mock.oneArg(cmpEq(new BigDecimal("1.5")))).andReturn("0");
-        replay(mock);
-        assertEquals("0", mock.oneArg(new BigDecimal("1.50")));
-        verify(mock);
-    }
-
-    public static class A {
-        private int value;
-
-        public A(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return value;
-        }
-    }
-
-    @Test
-    public void compareWithComparator() {
-        // Undertype just to make sure the generic typing works
-        Comparator<Object> comparator = new Comparator<Object>() {
-            private int compare(A a1, A a2) {
-                return a1.getValue() - a2.getValue();
-            }
-
-            public int compare(Object o1, Object o2) {
-                return compare((A)o1, (A)o2);
-            }
-        };
-
-        // Check my comparator works
-        assertTrue(comparator.compare(new A(1), new A(2)) < 0);
-        assertTrue(comparator.compare(new A(2), new A(1)) > 0);
-        assertTrue(comparator.compare(new A(1), new A(1)) == 0);
-
-        // Now test EasyMock.cmp
-        checkOrder(mock, true);
-        
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.EQUAL))).andReturn("0");
-        
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.GREATER))).andReturn("1");
-        
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.GREATER_OR_EQUAL))).andReturn("2");
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.GREATER_OR_EQUAL))).andReturn("2");
-        
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.LESS_OR_EQUAL))).andReturn("3");
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.LESS_OR_EQUAL))).andReturn("3");
-        
-        expect(mock.oneArg(cmp(new A(5), comparator, 
-                LogicalOperator.LESS_THAN))).andReturn("4");
-                
-        replay(mock);
-        
-        checkItFails(null); // null is not comparable so always return false
-        try {
-            mock.oneArg("");
-            fail();
-        }
-        catch(AssertionError e) {} // different type isn't either
-        
-        checkItFails(new A(4));
-        checkItFails(new A(6));
-        assertEquals("0", mock.oneArg(new A(5)));
-
-        checkItFails(new A(4));
-        checkItFails(new A(5));        
-        assertEquals("1", mock.oneArg(new A(6)));
-        
-        checkItFails(new A(4));
-        assertEquals("2", mock.oneArg(new A(6)));
-        assertEquals("2", mock.oneArg(new A(5)));
-        
-        checkItFails(new A(6));
-        assertEquals("3", mock.oneArg(new A(4)));
-        assertEquals("3", mock.oneArg(new A(5)));
-
-        checkItFails(new A(5));
-        checkItFails(new A(6));
-        assertEquals("4", mock.oneArg(new A(4)));
-        
-        verify(mock);
-    }
-
-    private void checkItFails(A a) {
-        try {
-            mock.oneArg(a);
-            fail();
-        }
-        catch(AssertionError e) {}
-    }
-
-    @Test
-    public void any() {
-        expect(mock.oneArg(anyBoolean())).andReturn("0");
-        expect(mock.oneArg(anyByte())).andReturn("1");
-        expect(mock.oneArg(anyChar())).andReturn("2");
-        expect(mock.oneArg(anyDouble())).andReturn("3");
-        expect(mock.oneArg(anyFloat())).andReturn("4");
-        expect(mock.oneArg(anyInt())).andReturn("5");
-        expect(mock.oneArg(anyLong())).andReturn("6");
-        expect(mock.oneArg(anyShort())).andReturn("7");
-        expect(mock.oneArg((String) anyObject())).andReturn("8");
-        expect(mock.oneArg((List<String>) EasyMock.<List<String>>anyObject())).andReturn("9"); // make sure there's no warning on the cast
-        replay(mock);
-        assertEquals("9", mock.oneArg(Collections.emptyList()));
-        assertEquals("0", mock.oneArg(true));
-        assertEquals("1", mock.oneArg((byte) 1));
-        assertEquals("2", mock.oneArg((char) 1));
-        assertEquals("3", mock.oneArg((double) 1));
-        assertEquals("7", mock.oneArg((short) 1));
-        assertEquals("8", mock.oneArg("Test"));
-        assertEquals("4", mock.oneArg((float) 1));
-        assertEquals("5", mock.oneArg((int) 1));
-        assertEquals("6", mock.oneArg((long) 1));
-        verify(mock);
-    }    
-
-    @Test
-    public void arrayEquals() {
-        expect(mock.oneArray(aryEq(new boolean[] { true }))).andReturn("0");
-        expect(mock.oneArray(aryEq(new byte[] { 1 }))).andReturn("1");
-        expect(mock.oneArray(aryEq(new char[] { 1 }))).andReturn("2");
-        expect(mock.oneArray(aryEq(new double[] { 1 }))).andReturn("3");
-        expect(mock.oneArray(aryEq(new float[] { 1 }))).andReturn("4");
-        expect(mock.oneArray(aryEq(new int[] { 1 }))).andReturn("5");
-        expect(mock.oneArray(aryEq(new long[] { 1 }))).andReturn("6");
-        expect(mock.oneArray(aryEq(new short[] { 1 }))).andReturn("7");
-        expect(mock.oneArray(aryEq(new String[] { "Test" }))).andReturn("8");
-        expect(mock.oneArray(aryEq(new Object[] { "Test" }))).andReturn("9");
-        replay(mock);
-        assertEquals("9", mock.oneArray(new Object[] { "Test" }));
-        assertEquals("0", mock.oneArray(new boolean[] { true }));
-        assertEquals("1", mock.oneArray(new byte[] { 1 }));
-        assertEquals("2", mock.oneArray(new char[] { 1 }));
-        assertEquals("3", mock.oneArray(new double[] { 1 }));
-        assertEquals("7", mock.oneArray(new short[] { 1 }));
-        assertEquals("8", mock.oneArray(new String[] { "Test" }));
-        assertEquals("4", mock.oneArray(new float[] { 1 }));
-        assertEquals("5", mock.oneArray(new int[] { 1 }));
-        assertEquals("6", mock.oneArray(new long[] { 1 }));
-        verify(mock);
-    }
-
-    @Test
-    public void greaterOrEqual() {
-        expect(mock.oneArg(geq(7))).andReturn("1").times(3);
-        expect(mock.oneArg(lt(7))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(7));
-        assertEquals("2", mock.oneArg(6));
-        assertEquals("1", mock.oneArg(8));
-        assertEquals("2", mock.oneArg(6));
-        assertEquals("1", mock.oneArg(9));
-
-        verify(mock);
-    }
-
-    @Test
-    public void greaterThan() {
-        expect(mock.oneArg(gt(7))).andReturn("1").times(3);
-        expect(mock.oneArg(leq(7))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(8));
-        assertEquals("2", mock.oneArg(7));
-        assertEquals("1", mock.oneArg(9));
-        assertEquals("2", mock.oneArg(6));
-        assertEquals("1", mock.oneArg(10));
-
-        verify(mock);
-    }
-
-    @Test
-    public void lessOrEqual() {
-        expect(mock.oneArg(leq(7))).andReturn("1").times(3);
-        expect(mock.oneArg(gt(7))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(7));
-        assertEquals("2", mock.oneArg(8));
-        assertEquals("1", mock.oneArg(6));
-        assertEquals("2", mock.oneArg(9));
-        assertEquals("1", mock.oneArg(5));
-
-        verify(mock);
-    }
-
-    @Test
-    public void lessThan() {
-        expect(mock.oneArg(lt(7))).andReturn("1").times(3);
-        expect(mock.oneArg(geq(7))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(5));
-        assertEquals("2", mock.oneArg(7));
-        assertEquals("1", mock.oneArg(6));
-        assertEquals("2", mock.oneArg(8));
-        assertEquals("1", mock.oneArg(4));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testOr() {
-        expect(mock.oneArg(or(eq(7), eq(9)))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(anyInt())).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(7));
-        assertEquals("1", mock.oneArg(9));
-        assertEquals("2", mock.oneArg(10));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testNull() {
-        expect(mock.threeArgumentMethod(eq(1), isNull(), eq("")))
-                .andReturn("1").atLeastOnce();
-        expect(mock.threeArgumentMethod(eq(1), not(isNull()), eq("")))
-                .andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.threeArgumentMethod(1, null, ""));
-        assertEquals("2", mock.threeArgumentMethod(1, new Object(), ""));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testNotNull() {
-        expect(mock.threeArgumentMethod(eq(1), notNull(), eq(""))).andReturn(
-                "1").atLeastOnce();
-        expect(mock.threeArgumentMethod(eq(1), not(notNull()), eq("")))
-                .andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.threeArgumentMethod(1, new Object(), ""));
-        assertEquals("2", mock.threeArgumentMethod(1, null, ""));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testFind() {
-        expect(mock.oneArg(find("[a-z]+\\d"))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(find("\\d\\d"))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg("1ab12"));
-        assertEquals("2", mock.oneArg("312xx"));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testMatches() {
-        expect(mock.oneArg(matches("[a-z]+\\d\\d"))).andReturn("1")
-                .atLeastOnce();
-        expect(mock.oneArg(matches("\\d\\d\\d"))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg("a12"));
-        assertEquals("2", mock.oneArg("131"));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testContains() {
-        expect(mock.oneArg(contains("ab"))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(contains("bc"))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg("xabcx"));
-        assertEquals("2", mock.oneArg("xdbcx"));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testStartsWith() {
-        expect(mock.oneArg(startsWith("ab"))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(startsWith("bc"))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg("abcx"));
-        assertEquals("2", mock.oneArg("bcxe"));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testEndsWith() {
-        expect(mock.oneArg(endsWith("ab"))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(endsWith("bc"))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg("xab"));
-        assertEquals("2", mock.oneArg("xbc"));
-
-        verify(mock);
-    }
-
-    @Test
-    public void equalsWithDelta() {
-        expect(mock.oneArg(eq(1.0D, 0.1D))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(eq(2.0D, 0.1D))).andStubReturn("2");
-        expect(mock.oneArg(eq(1.0F, 0.1F))).andReturn("3").atLeastOnce();
-        expect(mock.oneArg(eq(2.0F, 0.1F))).andStubReturn("4");
-        expect(mock.oneArg(eq(2.0F, 0.1F))).andStubReturn("4");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(1.0));
-        assertEquals("1", mock.oneArg(0.91));
-        assertEquals("1", mock.oneArg(1.09));
-        assertEquals("2", mock.oneArg(2.0));
-
-        assertEquals("3", mock.oneArg(1.0F));
-        assertEquals("3", mock.oneArg(0.91F));
-        assertEquals("3", mock.oneArg(1.09F));
-        assertEquals("4", mock.oneArg(2.0F));
-
-        verify(mock);
-    }
-
-    @Test
-    public void testSame() {
-        Object one = new String("1243");
-        Object two = new String("1243");
-
-        assertNotSame(one, two);
-        assertEquals(one, two);
-
-        expect(mock.oneArg(same(one))).andReturn("1").atLeastOnce();
-        expect(mock.oneArg(same(two))).andStubReturn("2");
-
-        replay(mock);
-
-        assertEquals("1", mock.oneArg(one));
-        assertEquals("2", mock.oneArg(two));
-
-        verify(mock);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.easymock.LogicalOperator;
+import org.easymock.internal.matchers.Equals;
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageConstraintsTest {
+    private IMethods mock;
+
+    @Before
+    public void setUp() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void equalsMissing() {
+        mock.simpleMethodWithArgument(not(eq("asd")));
+        try {
+            mock.simpleMethodWithArgument(not("jkl"));
+            fail();
+        } catch (final IllegalStateException e) {
+            assertEquals("no matchers found.", e.getMessage());
+        }
+        try {
+            mock.simpleMethodWithArgument(or(eq("jkl"), "asd"));
+            fail();
+        } catch (final IllegalStateException e) {
+            assertEquals("2 matchers expected, 1 recorded.", e.getMessage());
+        }
+        try {
+            mock.threeArgumentMethod(1, "asd", eq("asd"));
+            fail();
+        } catch (final IllegalStateException e) {
+            assertEquals(
+                    "3 matchers expected, 1 recorded.\n"
+                            + "This exception usually occurs when matchers are mixed with raw values when recording a method:\n"
+                            + "\tfoo(5, eq(6));\t// wrong\n"
+                            + "You need to use no matcher at all or a matcher for every single param:\n"
+                            + "\tfoo(eq(5), eq(6));\t// right\n" + "\tfoo(5, 6);\t// also right",
+                    e.getMessage());
+        }
+
+    }
+
+    @Test
+    public void differentConstraintsOnSameCall() {
+        mock.simpleMethodWithArgument((String) isNull());
+        mock.simpleMethodWithArgument((String) notNull());
+        replay(mock);
+        mock.simpleMethodWithArgument(null);
+        mock.simpleMethodWithArgument("2");
+    }
+
+    @Test
+    public void equals() {
+        assertEquals(new Equals(null), new Equals(null));
+        assertEquals(new Equals(new Integer(2)), new Equals(new Integer(2)));
+        assertFalse(new Equals(null).equals(null));
+        assertFalse(new Equals(null).equals("Test"));
+        try {
+            new Equals(null).hashCode();
+            fail();
+        } catch (final UnsupportedOperationException expected) {
+        }
+    }
+
+    @Test
+    public void constraints() {
+        expect(mock.threeArgumentMethod(and(geq(7), leq(10)), isA(String.class), contains("123"))).andReturn(
+                "456").atLeastOnce();
+        replay(mock);
+        boolean failed = false;
+        try {
+            mock.threeArgumentMethod(11, "", "01234");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail();
+        }
+        failed = false;
+        try {
+            mock.threeArgumentMethod(8, new Object(), "01234");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail();
+        }
+        failed = false;
+        try {
+            mock.threeArgumentMethod(8, "", "no match");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail();
+        }
+        assertEquals("456", mock.threeArgumentMethod(8, "", "01234"));
+        verify(mock);
+    }
+
+    @Test
+    public void andOverloaded() {
+        expect(mock.oneArg(and(eq(false), eq(false)))).andReturn("0");
+        expect(mock.oneArg(and(eq((byte) 1), eq((byte) 1)))).andReturn("1");
+        expect(mock.oneArg(and(eq('a'), eq('a')))).andReturn("2");
+        expect(mock.oneArg(and(eq((double) 1), eq((double) 1)))).andReturn("3");
+        expect(mock.oneArg(and(eq((float) 1), eq((float) 1)))).andReturn("4");
+        expect(mock.oneArg(and(eq(1), eq(1)))).andReturn("5");
+        expect(mock.oneArg(and(eq((long) 1), eq((long) 1)))).andReturn("6");
+        expect(mock.oneArg(and(eq((short) 1), eq((short) 1)))).andReturn("7");
+        expect(mock.oneArg(and(contains("a"), contains("d")))).andReturn("8");
+        expect(mock.oneArg(and(isA(Class.class), eq(Object.class)))).andReturn("9");
+        replay(mock);
+        assertEquals("9", mock.oneArg(Object.class));
+        assertEquals("0", mock.oneArg(false));
+        assertEquals("1", mock.oneArg((byte) 1));
+        assertEquals("2", mock.oneArg('a'));
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("7", mock.oneArg((short) 1));
+        assertEquals("8", mock.oneArg("abcde"));
+        assertEquals("4", mock.oneArg((float) 1));
+        assertEquals("5", mock.oneArg(1));
+        assertEquals("6", mock.oneArg((long) 1));
+        verify(mock);
+    }
+
+    @Test
+    public void orOverloaded() {
+        expect(mock.oneArg(or(eq(false), eq(true)))).andReturn("0");
+        expect(mock.oneArg(or(eq((byte) 1), eq((byte) 2)))).andReturn("1");
+        expect(mock.oneArg(or(eq((char) 1), eq((char) 2)))).andReturn("2");
+        expect(mock.oneArg(or(eq((double) 1), eq((double) 2)))).andReturn("3");
+        expect(mock.oneArg(or(eq((float) 1), eq((float) 2)))).andReturn("4");
+        expect(mock.oneArg(or(eq(1), eq(2)))).andReturn("5");
+        expect(mock.oneArg(or(eq((long) 1), eq((long) 2)))).andReturn("6");
+        expect(mock.oneArg(or(eq((short) 1), eq((short) 2)))).andReturn("7");
+        expect(mock.oneArg(or(eq("asd"), eq("jkl")))).andReturn("8");
+        expect(mock.oneArg(or(eq(this.getClass()), eq(Object.class)))).andReturn("9");
+        replay(mock);
+        assertEquals("9", mock.oneArg(Object.class));
+        assertEquals("0", mock.oneArg(true));
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals("2", mock.oneArg((char) 1));
+        assertEquals("3", mock.oneArg((double) 2));
+        assertEquals("7", mock.oneArg((short) 1));
+        assertEquals("8", mock.oneArg("jkl"));
+        assertEquals("4", mock.oneArg((float) 1));
+        assertEquals("5", mock.oneArg(2));
+        assertEquals("6", mock.oneArg((long) 1));
+        verify(mock);
+    }
+
+    @Test
+    public void notOverloaded() {
+        expect(mock.oneArg(not(eq(false)))).andReturn("0");
+        expect(mock.oneArg(not(eq((byte) 1)))).andReturn("1");
+        expect(mock.oneArg(not(eq('a')))).andReturn("2");
+        expect(mock.oneArg(not(eq((double) 1)))).andReturn("3");
+        expect(mock.oneArg(not(eq((float) 1)))).andReturn("4");
+        expect(mock.oneArg(not(eq(1)))).andReturn("5");
+        expect(mock.oneArg(not(eq((long) 1)))).andReturn("6");
+        expect(mock.oneArg(not(eq((short) 1)))).andReturn("7");
+        expect(mock.oneArg(not(contains("a")))).andReturn("8");
+        expect(mock.oneArg(not(isA(Class.class)))).andReturn("9");
+        replay(mock);
+        assertEquals("9", mock.oneArg(new Object()));
+        assertEquals("0", mock.oneArg(true));
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals("2", mock.oneArg('b'));
+        assertEquals("3", mock.oneArg((double) 2));
+        assertEquals("7", mock.oneArg((short) 2));
+        assertEquals("8", mock.oneArg("bcde"));
+        assertEquals("4", mock.oneArg((float) 2));
+        assertEquals("5", mock.oneArg(2));
+        assertEquals("6", mock.oneArg((long) 2));
+        verify(mock);
+    }
+
+    @Test
+    public void lessOrEqualOverloaded() {
+        expect(mock.oneArg(leq((byte) 1))).andReturn("1");
+        expect(mock.oneArg(leq((double) 1))).andReturn("3");
+        expect(mock.oneArg(leq((float) 1))).andReturn("4");
+        expect(mock.oneArg(leq(1))).andReturn("5");
+        expect(mock.oneArg(leq((long) 1))).andReturn("6");
+        expect(mock.oneArg(leq((short) 1))).andReturn("7");
+        expect(mock.oneArg(leq(new BigDecimal("1")))).andReturn("8");
+        replay(mock);
+        assertEquals("1", mock.oneArg((byte) 1));
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("7", mock.oneArg((short) 0));
+        assertEquals("4", mock.oneArg((float) -5));
+        assertEquals("5", mock.oneArg(-2));
+        assertEquals("6", mock.oneArg((long) -3));
+        assertEquals("8", mock.oneArg(new BigDecimal("0.5")));
+        verify(mock);
+    }
+
+    @Test
+    public void lessThanOverloaded() {
+        expect(mock.oneArg(lt((byte) 1))).andReturn("1");
+        expect(mock.oneArg(lt((double) 1))).andReturn("3");
+        expect(mock.oneArg(lt((float) 1))).andReturn("4");
+        expect(mock.oneArg(lt(1))).andReturn("5");
+        expect(mock.oneArg(lt((long) 1))).andReturn("6");
+        expect(mock.oneArg(lt((short) 1))).andReturn("7");
+        expect(mock.oneArg(lt(new BigDecimal("1")))).andReturn("8");
+        replay(mock);
+        assertEquals("1", mock.oneArg((byte) 0));
+        assertEquals("3", mock.oneArg((double) 0));
+        assertEquals("7", mock.oneArg((short) 0));
+        assertEquals("4", mock.oneArg((float) -4));
+        assertEquals("5", mock.oneArg(-34));
+        assertEquals("6", mock.oneArg((long) -6));
+        assertEquals("8", mock.oneArg(new BigDecimal("0.5")));
+        verify(mock);
+    }
+
+    @Test
+    public void greaterOrEqualOverloaded() {
+        expect(mock.oneArg(geq((byte) 1))).andReturn("1");
+        expect(mock.oneArg(geq((double) 1))).andReturn("3");
+        expect(mock.oneArg(geq((float) 1))).andReturn("4");
+        expect(mock.oneArg(geq(1))).andReturn("5");
+        expect(mock.oneArg(geq((long) 1))).andReturn("6");
+        expect(mock.oneArg(geq((short) 1))).andReturn("7");
+        expect(mock.oneArg(geq(new BigDecimal("1")))).andReturn("8");
+        replay(mock);
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("7", mock.oneArg((short) 2));
+        assertEquals("4", mock.oneArg((float) 3));
+        assertEquals("5", mock.oneArg(4));
+        assertEquals("6", mock.oneArg((long) 5));
+        assertEquals("8", mock.oneArg(new BigDecimal("1.5")));
+        verify(mock);
+    }
+
+    @Test
+    public void greaterThanOverloaded() {
+        expect(mock.oneArg(gt((byte) 1))).andReturn("1");
+        expect(mock.oneArg(gt((double) 1))).andReturn("3");
+        expect(mock.oneArg(gt((float) 1))).andReturn("4");
+        expect(mock.oneArg(gt(1))).andReturn("5");
+        expect(mock.oneArg(gt((long) 1))).andReturn("6");
+        expect(mock.oneArg(gt((short) 1))).andReturn("7");
+        expect(mock.oneArg(gt(new BigDecimal("1")))).andReturn("8");
+        replay(mock);
+        assertEquals("1", mock.oneArg((byte) 2));
+        assertEquals("3", mock.oneArg((double) 2));
+        assertEquals("7", mock.oneArg((short) 2));
+        assertEquals("4", mock.oneArg((float) 3));
+        assertEquals("5", mock.oneArg(2));
+        assertEquals("6", mock.oneArg((long) 5));
+        assertEquals("8", mock.oneArg(new BigDecimal("1.5")));
+        verify(mock);
+    }
+
+    @Test
+    public void cmpTo() {
+        expect(mock.oneArg(cmpEq(new BigDecimal("1.5")))).andReturn("0");
+        replay(mock);
+        assertEquals("0", mock.oneArg(new BigDecimal("1.50")));
+        verify(mock);
+    }
+
+    public static class A {
+        private final int value;
+
+        public A(final int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    @Test
+    public void compareWithComparator() {
+        // Undertype just to make sure the generic typing works
+        final Comparator<Object> comparator = new Comparator<Object>() {
+            private int compare(final A a1, final A a2) {
+                return a1.getValue() - a2.getValue();
+            }
+
+            public int compare(final Object o1, final Object o2) {
+                return compare((A) o1, (A) o2);
+            }
+        };
+
+        // Check my comparator works
+        assertTrue(comparator.compare(new A(1), new A(2)) < 0);
+        assertTrue(comparator.compare(new A(2), new A(1)) > 0);
+        assertTrue(comparator.compare(new A(1), new A(1)) == 0);
+
+        // Now test EasyMock.cmp
+        checkOrder(mock, true);
+
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.EQUAL))).andReturn("0");
+
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.GREATER))).andReturn("1");
+
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.GREATER_OR_EQUAL))).andReturn("2");
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.GREATER_OR_EQUAL))).andReturn("2");
+
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.LESS_OR_EQUAL))).andReturn("3");
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.LESS_OR_EQUAL))).andReturn("3");
+
+        expect(mock.oneArg(cmp(new A(5), comparator, LogicalOperator.LESS_THAN))).andReturn("4");
+
+        replay(mock);
+
+        checkItFails(null); // null is not comparable so always return false
+        try {
+            mock.oneArg("");
+            fail();
+        } catch (final AssertionError e) {
+        } // different type isn't either
+
+        checkItFails(new A(4));
+        checkItFails(new A(6));
+        assertEquals("0", mock.oneArg(new A(5)));
+
+        checkItFails(new A(4));
+        checkItFails(new A(5));
+        assertEquals("1", mock.oneArg(new A(6)));
+
+        checkItFails(new A(4));
+        assertEquals("2", mock.oneArg(new A(6)));
+        assertEquals("2", mock.oneArg(new A(5)));
+
+        checkItFails(new A(6));
+        assertEquals("3", mock.oneArg(new A(4)));
+        assertEquals("3", mock.oneArg(new A(5)));
+
+        checkItFails(new A(5));
+        checkItFails(new A(6));
+        assertEquals("4", mock.oneArg(new A(4)));
+
+        verify(mock);
+    }
+
+    private void checkItFails(final A a) {
+        try {
+            mock.oneArg(a);
+            fail();
+        } catch (final AssertionError e) {
+        }
+    }
+
+    @Test
+    public void any() {
+        expect(mock.oneArg(anyBoolean())).andReturn("0");
+        expect(mock.oneArg(anyByte())).andReturn("1");
+        expect(mock.oneArg(anyChar())).andReturn("2");
+        expect(mock.oneArg(anyDouble())).andReturn("3");
+        expect(mock.oneArg(anyFloat())).andReturn("4");
+        expect(mock.oneArg(anyInt())).andReturn("5");
+        expect(mock.oneArg(anyLong())).andReturn("6");
+        expect(mock.oneArg(anyShort())).andReturn("7");
+        expect(mock.oneArg((String) anyObject())).andReturn("8");
+        expect(mock.oneArg(anyObject(String.class))).andReturn("9");
+        expect(mock.oneArg(EasyMock.<List<String>> anyObject())).andReturn("9"); // make sure there's no warning on the cast
+        expect(mock.oneArg(anyString())).andReturn("10");
+        replay(mock);
+        assertEquals("9", mock.oneArg(Collections.emptyList()));
+        assertEquals("0", mock.oneArg(true));
+        assertEquals("1", mock.oneArg((byte) 1));
+        assertEquals("2", mock.oneArg((char) 1));
+        assertEquals("3", mock.oneArg((double) 1));
+        assertEquals("7", mock.oneArg((short) 1));
+        assertEquals("8", mock.oneArg("Test"));
+        assertEquals("4", mock.oneArg((float) 1));
+        assertEquals("5", mock.oneArg(1));
+        assertEquals("6", mock.oneArg((long) 1));
+        assertEquals("9", mock.oneArg("Other Test"));
+        assertEquals("10", mock.oneArg(""));
+        verify(mock);
+    }
+
+    @Test
+    public void arrayEquals() {
+        expect(mock.oneArray(aryEq(new boolean[] { true }))).andReturn("0");
+        expect(mock.oneArray(aryEq(new byte[] { 1 }))).andReturn("1");
+        expect(mock.oneArray(aryEq(new char[] { 1 }))).andReturn("2");
+        expect(mock.oneArray(aryEq(new double[] { 1 }))).andReturn("3");
+        expect(mock.oneArray(aryEq(new float[] { 1 }))).andReturn("4");
+        expect(mock.oneArray(aryEq(new int[] { 1 }))).andReturn("5");
+        expect(mock.oneArray(aryEq(new long[] { 1 }))).andReturn("6");
+        expect(mock.oneArray(aryEq(new short[] { 1 }))).andReturn("7");
+        expect(mock.oneArray(aryEq(new String[] { "Test" }))).andReturn("8");
+        expect(mock.oneArray(aryEq(new Object[] { "Test" }))).andReturn("9");
+        replay(mock);
+        assertEquals("9", mock.oneArray(new Object[] { "Test" }));
+        assertEquals("0", mock.oneArray(new boolean[] { true }));
+        assertEquals("1", mock.oneArray(new byte[] { 1 }));
+        assertEquals("2", mock.oneArray(new char[] { 1 }));
+        assertEquals("3", mock.oneArray(new double[] { 1 }));
+        assertEquals("7", mock.oneArray(new short[] { 1 }));
+        assertEquals("8", mock.oneArray(new String[] { "Test" }));
+        assertEquals("4", mock.oneArray(new float[] { 1 }));
+        assertEquals("5", mock.oneArray(new int[] { 1 }));
+        assertEquals("6", mock.oneArray(new long[] { 1 }));
+        verify(mock);
+    }
+
+    @Test
+    public void greaterOrEqual() {
+        expect(mock.oneArg(geq(7))).andReturn("1").times(3);
+        expect(mock.oneArg(lt(7))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(7));
+        assertEquals("2", mock.oneArg(6));
+        assertEquals("1", mock.oneArg(8));
+        assertEquals("2", mock.oneArg(6));
+        assertEquals("1", mock.oneArg(9));
+
+        verify(mock);
+    }
+
+    @Test
+    public void greaterThan() {
+        expect(mock.oneArg(gt(7))).andReturn("1").times(3);
+        expect(mock.oneArg(leq(7))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(8));
+        assertEquals("2", mock.oneArg(7));
+        assertEquals("1", mock.oneArg(9));
+        assertEquals("2", mock.oneArg(6));
+        assertEquals("1", mock.oneArg(10));
+
+        verify(mock);
+    }
+
+    @Test
+    public void lessOrEqual() {
+        expect(mock.oneArg(leq(7))).andReturn("1").times(3);
+        expect(mock.oneArg(gt(7))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(7));
+        assertEquals("2", mock.oneArg(8));
+        assertEquals("1", mock.oneArg(6));
+        assertEquals("2", mock.oneArg(9));
+        assertEquals("1", mock.oneArg(5));
+
+        verify(mock);
+    }
+
+    @Test
+    public void lessThan() {
+        expect(mock.oneArg(lt(7))).andReturn("1").times(3);
+        expect(mock.oneArg(geq(7))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(5));
+        assertEquals("2", mock.oneArg(7));
+        assertEquals("1", mock.oneArg(6));
+        assertEquals("2", mock.oneArg(8));
+        assertEquals("1", mock.oneArg(4));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testOr() {
+        expect(mock.oneArg(or(eq(7), eq(9)))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(anyInt())).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(7));
+        assertEquals("1", mock.oneArg(9));
+        assertEquals("2", mock.oneArg(10));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testNull() {
+        expect(mock.threeArgumentMethod(eq(1), isNull(), eq(""))).andReturn("1");
+        expect(mock.threeArgumentMethod(eq(1), isNull(Object.class), eq(""))).andReturn("2");
+        expect(mock.threeArgumentMethod(eq(1), not(isNull()), eq(""))).andStubReturn("3");
+
+        replay(mock);
+
+        assertEquals("1", mock.threeArgumentMethod(1, null, ""));
+        assertEquals("2", mock.threeArgumentMethod(1, null, ""));
+        assertEquals("3", mock.threeArgumentMethod(1, new Object(), ""));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testNotNull() {
+        expect(mock.threeArgumentMethod(eq(1), notNull(), eq(""))).andReturn("1");
+        expect(mock.threeArgumentMethod(eq(1), notNull(Object.class), eq(""))).andReturn("2");
+        expect(mock.threeArgumentMethod(eq(1), not(notNull()), eq(""))).andStubReturn("3");
+
+        replay(mock);
+
+        assertEquals("1", mock.threeArgumentMethod(1, new Object(), ""));
+        assertEquals("2", mock.threeArgumentMethod(1, new Object(), ""));
+        assertEquals("3", mock.threeArgumentMethod(1, null, ""));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testFind() {
+        expect(mock.oneArg(find("[a-z]+\\d"))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(find("\\d\\d"))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg("1ab12"));
+        assertEquals("2", mock.oneArg("312xx"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testMatches() {
+        expect(mock.oneArg(matches("[a-z]+\\d\\d"))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(matches("\\d\\d\\d"))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg("a12"));
+        assertEquals("2", mock.oneArg("131"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testContains() {
+        expect(mock.oneArg(contains("ab"))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(contains("bc"))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg("xabcx"));
+        assertEquals("2", mock.oneArg("xdbcx"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testStartsWith() {
+        expect(mock.oneArg(startsWith("ab"))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(startsWith("bc"))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg("abcx"));
+        assertEquals("2", mock.oneArg("bcxe"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testEndsWith() {
+        expect(mock.oneArg(endsWith("ab"))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(endsWith("bc"))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg("xab"));
+        assertEquals("2", mock.oneArg("xbc"));
+
+        verify(mock);
+    }
+
+    @Test
+    public void equalsWithDelta() {
+        expect(mock.oneArg(eq(1.0D, 0.1D))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(eq(2.0D, 0.1D))).andStubReturn("2");
+        expect(mock.oneArg(eq(1.0F, 0.1F))).andReturn("3").atLeastOnce();
+        expect(mock.oneArg(eq(2.0F, 0.1F))).andStubReturn("4");
+        expect(mock.oneArg(eq(2.0F, 0.1F))).andStubReturn("4");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(1.0));
+        assertEquals("1", mock.oneArg(0.91));
+        assertEquals("1", mock.oneArg(1.09));
+        assertEquals("2", mock.oneArg(2.0));
+
+        assertEquals("3", mock.oneArg(1.0F));
+        assertEquals("3", mock.oneArg(0.91F));
+        assertEquals("3", mock.oneArg(1.09F));
+        assertEquals("4", mock.oneArg(2.0F));
+
+        verify(mock);
+    }
+
+    @Test
+    public void testSame() {
+        final Object one = new String("1243");
+        final Object two = new String("1243");
+
+        assertNotSame(one, two);
+        assertEquals(one, two);
+
+        expect(mock.oneArg(same(one))).andReturn("1").atLeastOnce();
+        expect(mock.oneArg(same(two))).andStubReturn("2");
+
+        replay(mock);
+
+        assertEquals("1", mock.oneArg(one));
+        assertEquals("2", mock.oneArg(two));
+
+        verify(mock);
+    }
+}
diff --git a/tests/org/easymock/tests2/UsageMatchersTest.java b/tests/org/easymock/tests2/UsageMatchersTest.java
index d6696fc..ba7e426 100644
--- a/tests/org/easymock/tests2/UsageMatchersTest.java
+++ b/tests/org/easymock/tests2/UsageMatchersTest.java
@@ -1,22 +1,36 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-
-import org.easymock.tests.IMethods;
-import org.junit.Test;
-
-public class UsageMatchersTest {
-    @Test(expected = IllegalStateException.class)
-    public void additionalMatchersFailAtReplay() {
-
-        IMethods mock = createMock(IMethods.class);
-        lt(5);
-
-        replay(mock);
-    }
-
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+
+import org.easymock.tests.IMethods;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageMatchersTest {
+    @Test(expected = IllegalStateException.class)
+    public void additionalMatchersFailAtReplay() {
+
+        final IMethods mock = createMock(IMethods.class);
+        lt(5);
+
+        replay(mock);
+    }
+
+}
diff --git a/tests/org/easymock/tests2/UsageStrictMockTest.java b/tests/org/easymock/tests2/UsageStrictMockTest.java
index 655e3f2..404acbf 100644
--- a/tests/org/easymock/tests2/UsageStrictMockTest.java
+++ b/tests/org/easymock/tests2/UsageStrictMockTest.java
@@ -1,200 +1,208 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.internal.ReplayState;
-import org.easymock.tests.IMethods;
-import org.easymock.tests.Util;
-import org.junit.Before;
-import org.junit.Test;
-
-public class UsageStrictMockTest {
-    private IMethods mock;
-
-    @Before
-    public void setup() {
-        mock = createStrictMock(IMethods.class);
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-        replay(mock);
-    }
-
-    @Test
-    public void orderedCallsSucces() {
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-        verify(mock);
-    }
-
-    @Test
-    public void unorderedCallsFailure() {
-        boolean failed = false;
-        try {
-            mock.simpleMethodWithArgument("2");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail("unordered calls accepted");
-        }
-    }
-
-    @Test
-    public void tooManyCallsFailure() {
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        boolean failed = false;
-        try {
-            mock.simpleMethodWithArgument("2");
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed) {
-            fail("too many calls accepted");
-        }
-    }
-
-    @Test
-    public void tooFewCallsFailure() {
-        mock.simpleMethodWithArgument("1");
-        boolean failed = false;
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertTrue("stack trace must be filled in", Util.getStackTrace(
-                    expected).indexOf(ReplayState.class.getName()) == -1);
-        }
-        if (!failed) {
-            fail("too few calls accepted");
-        }
-    }
-
-    @Test
-    public void differentMethods() {
-
-        reset(mock);
-
-        mock.booleanReturningMethod(0);
-        expectLastCall().andReturn(true);
-        mock.simpleMethod();
-        mock.booleanReturningMethod(1);
-        expectLastCall().andReturn(false).times(2, 3);
-        mock.simpleMethod();
-        expectLastCall().atLeastOnce();
-
-        replay(mock);
-        assertEquals(true, mock.booleanReturningMethod(0));
-        mock.simpleMethod();
-
-        boolean failed = false;
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    simpleMethod(): expected: 1, actual: 1"
-                            + "\n    booleanReturningMethod(1): expected: between 2 and 3, actual: 0"
-                            + "\n    simpleMethod(): expected: at least 1, actual: 0",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("too few calls accepted");
-        }
-
-        assertEquals(false, mock.booleanReturningMethod(1));
-
-        failed = false;
-        try {
-            mock.simpleMethod();
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Unexpected method call simpleMethod():"
-                            + "\n    booleanReturningMethod(1): expected: between 2 and 3, actual: 1",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("wrong call accepted");
-        }
-    }
-
-    @Test
-    public void range() {
-
-        reset(mock);
-
-        mock.booleanReturningMethod(0);
-        expectLastCall().andReturn(true);
-        mock.simpleMethod();
-        mock.booleanReturningMethod(1);
-        expectLastCall().andReturn(false).times(2, 3);
-        mock.simpleMethod();
-        expectLastCall().atLeastOnce();
-        expect(mock.booleanReturningMethod(1)).andReturn(false);
-
-        replay(mock);
-
-        mock.booleanReturningMethod(0);
-        mock.simpleMethod();
-
-        mock.booleanReturningMethod(1);
-        mock.booleanReturningMethod(1);
-        mock.booleanReturningMethod(1);
-
-        boolean failed = false;
-
-        try {
-            mock.booleanReturningMethod(1);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Unexpected method call booleanReturningMethod(1):"
-                            + "\n    booleanReturningMethod(1): expected: between 2 and 3, actual: 3 (+1)"
-                            + "\n    simpleMethod(): expected: at least 1, actual: 0",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("too many calls accepted");
-        }
-    }
-
-    @Test
-    public void stubBehavior() {
-        reset(mock);
-
-        mock.booleanReturningMethod(1);
-        expectLastCall().andReturn(true).andReturn(false).andReturn(true);
-        mock.booleanReturningMethod(anyInt());
-        expectLastCall().andStubReturn(true);
-
-        replay(mock);
-
-        assertEquals(true, mock.booleanReturningMethod(2));
-        assertEquals(true, mock.booleanReturningMethod(3));
-        assertEquals(true, mock.booleanReturningMethod(1));
-        assertEquals(false, mock.booleanReturningMethod(1));
-        assertEquals(true, mock.booleanReturningMethod(3));
-
-        boolean failed = false;
-        try {
-            verify(mock);
-        } catch (AssertionError expected) {
-            failed = true;
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    booleanReturningMethod(1): expected: 3, actual: 2",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("too few calls accepted");
-        }
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.internal.ReplayState;
+import org.easymock.tests.IMethods;
+import org.easymock.tests.Util;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageStrictMockTest {
+    private IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createStrictMock(IMethods.class);
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+        replay(mock);
+    }
+
+    @Test
+    public void orderedCallsSucces() {
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+        verify(mock);
+    }
+
+    @Test
+    public void unorderedCallsFailure() {
+        boolean failed = false;
+        try {
+            mock.simpleMethodWithArgument("2");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail("unordered calls accepted");
+        }
+    }
+
+    @Test
+    public void tooManyCallsFailure() {
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        boolean failed = false;
+        try {
+            mock.simpleMethodWithArgument("2");
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed) {
+            fail("too many calls accepted");
+        }
+    }
+
+    @Test
+    public void tooFewCallsFailure() {
+        mock.simpleMethodWithArgument("1");
+        boolean failed = false;
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertTrue("stack trace must be filled in", Util.getStackTrace(expected).indexOf(
+                    ReplayState.class.getName()) == -1);
+        }
+        if (!failed) {
+            fail("too few calls accepted");
+        }
+    }
+
+    @Test
+    public void differentMethods() {
+
+        reset(mock);
+
+        mock.booleanReturningMethod(0);
+        expectLastCall().andReturn(true);
+        mock.simpleMethod();
+        mock.booleanReturningMethod(1);
+        expectLastCall().andReturn(false).times(2, 3);
+        mock.simpleMethod();
+        expectLastCall().atLeastOnce();
+
+        replay(mock);
+        assertEquals(true, mock.booleanReturningMethod(0));
+        mock.simpleMethod();
+
+        boolean failed = false;
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.simpleMethod(): expected: 1, actual: 1"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: between 2 and 3, actual: 0"
+                    + "\n    IMethods.simpleMethod(): expected: at least 1, actual: 0", expected.getMessage());
+        }
+        if (!failed) {
+            fail("too few calls accepted");
+        }
+
+        assertEquals(false, mock.booleanReturningMethod(1));
+
+        failed = false;
+        try {
+            mock.simpleMethod();
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Unexpected method call IMethods.simpleMethod():"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: between 2 and 3, actual: 1",
+                    expected.getMessage());
+        }
+        if (!failed) {
+            fail("wrong call accepted");
+        }
+    }
+
+    @Test
+    public void range() {
+
+        reset(mock);
+
+        mock.booleanReturningMethod(0);
+        expectLastCall().andReturn(true);
+        mock.simpleMethod();
+        mock.booleanReturningMethod(1);
+        expectLastCall().andReturn(false).times(2, 3);
+        mock.simpleMethod();
+        expectLastCall().atLeastOnce();
+        expect(mock.booleanReturningMethod(1)).andReturn(false);
+
+        replay(mock);
+
+        mock.booleanReturningMethod(0);
+        mock.simpleMethod();
+
+        mock.booleanReturningMethod(1);
+        mock.booleanReturningMethod(1);
+        mock.booleanReturningMethod(1);
+
+        boolean failed = false;
+
+        try {
+            mock.booleanReturningMethod(1);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Unexpected method call IMethods.booleanReturningMethod(1):"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: between 2 and 3, actual: 4"
+                    + "\n    IMethods.simpleMethod(): expected: at least 1, actual: 0", expected.getMessage());
+        }
+        if (!failed) {
+            fail("too many calls accepted");
+        }
+    }
+
+    @Test
+    public void stubBehavior() {
+        reset(mock);
+
+        mock.booleanReturningMethod(1);
+        expectLastCall().andReturn(true).andReturn(false).andReturn(true);
+        mock.booleanReturningMethod(anyInt());
+        expectLastCall().andStubReturn(true);
+
+        replay(mock);
+
+        assertEquals(true, mock.booleanReturningMethod(2));
+        assertEquals(true, mock.booleanReturningMethod(3));
+        assertEquals(true, mock.booleanReturningMethod(1));
+        assertEquals(false, mock.booleanReturningMethod(1));
+        assertEquals(true, mock.booleanReturningMethod(3));
+
+        boolean failed = false;
+        try {
+            verify(mock);
+        } catch (final AssertionError expected) {
+            failed = true;
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.booleanReturningMethod(1): expected: 3, actual: 2", expected
+                    .getMessage());
+        }
+        if (!failed) {
+            fail("too few calls accepted");
+        }
+    }
+}
diff --git a/tests/org/easymock/tests2/UsageTest.java b/tests/org/easymock/tests2/UsageTest.java
index 988fb41..ae691ab 100644
--- a/tests/org/easymock/tests2/UsageTest.java
+++ b/tests/org/easymock/tests2/UsageTest.java
@@ -1,305 +1,312 @@
-/*
- * Copyright (c) 2001-2008 OFFIS, Tammo Freese.
- * This program is made available under the terms of the MIT License.
- */
-package org.easymock.tests2;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import org.easymock.tests.IMethods;
-import org.junit.Before;
-import org.junit.Test;
-
-public class UsageTest {
-
-    IMethods mock;
-
-    @Before
-    public void setup() {
-        mock = createMock(IMethods.class);
-    }
-
-    @Test
-    public void exactCallCountByLastCall() {
-        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2");
-        replay(mock);
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-
-        boolean failed = false;
-        try {
-            mock.oneArg(false);
-        } catch (AssertionError expected) {
-            failed = true;
-        }
-        if (!failed)
-            fail("expected AssertionError");
-    }
-
-    @Test
-    public void openCallCountByLastCall() {
-        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2")
-                .atLeastOnce();
-
-        replay(mock);
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-    }
-
-    @Test
-    public void exactCallCountByLastThrowable() {
-        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2")
-                .andThrow(new IndexOutOfBoundsException());
-
-        replay(mock);
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-
-        try {
-            mock.oneArg(false);
-            fail();
-        } catch (IndexOutOfBoundsException expected) {
-        }
-
-        boolean failed = true;
-        try {
-            mock.oneArg(false);
-            failed = false;
-        } catch (AssertionError expected) {
-        }
-        if (!failed)
-            fail("expected AssertionError");
-    }
-
-    @Test
-    public void openCallCountByLastThrowable() {
-        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2")
-                .andThrow(new IndexOutOfBoundsException()).atLeastOnce();
-
-        replay(mock);
-
-        assertEquals("Test", mock.oneArg(false));
-        assertEquals("Test2", mock.oneArg(false));
-
-        try {
-            mock.oneArg(false);
-        } catch (IndexOutOfBoundsException expected) {
-        }
-        try {
-            mock.oneArg(false);
-        } catch (IndexOutOfBoundsException expected) {
-        }
-    }
-
-    @Test
-    public void moreThanOneArgument() {
-        expect(mock.threeArgumentMethod(1, "2", "3")).andReturn("Test")
-                .times(2);
-
-        replay(mock);
-
-        assertEquals("Test", mock.threeArgumentMethod(1, "2", "3"));
-
-        boolean failed = true;
-        try {
-            verify(mock);
-            failed = false;
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Expectation failure on verify:"
-                            + "\n    threeArgumentMethod(1, \"2\", \"3\"): expected: 2, actual: 1",
-                    expected.getMessage());
-        }
-        if (!failed) {
-            fail("exception expected");
-        }
-    }
-
-    @Test
-    public void wrongArguments() {
-        mock.simpleMethodWithArgument("3");
-        replay(mock);
-
-        try {
-            mock.simpleMethodWithArgument("5");
-            fail();
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call simpleMethodWithArgument(\"5\"):"
-                            + "\n    simpleMethodWithArgument(\"3\"): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void summarizeSameObjectArguments() {
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("3");
-        replay(mock);
-
-        try {
-            mock.simpleMethodWithArgument("5");
-            fail();
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call simpleMethodWithArgument(\"5\"):"
-                            + "\n    simpleMethodWithArgument(\"3\"): expected: 2, actual: 0",
-                    expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void argumentsOrdered() {
-        mock.simpleMethodWithArgument("4");
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("2");
-        mock.simpleMethodWithArgument("0");
-        mock.simpleMethodWithArgument("1");
-        replay(mock);
-
-        try {
-            mock.simpleMethodWithArgument("5");
-            fail("exception expected");
-        } catch (AssertionError expected) {
-            assertEquals(
-                    "\n  Unexpected method call simpleMethodWithArgument(\"5\"):"
-                            + "\n    simpleMethodWithArgument(\"4\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"3\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"2\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"0\"): expected: 1, actual: 0"
-                            + "\n    simpleMethodWithArgument(\"1\"): expected: 1, actual: 0",
-                    expected.getMessage());
-        }
-
-    }
-
-    @Test
-    public void mixingOrderedAndUnordered() {
-        mock.simpleMethodWithArgument("2");
-        mock.simpleMethodWithArgument("1");
-        checkOrder(mock, true);
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("4");
-        checkOrder(mock, false);
-        mock.simpleMethodWithArgument("6");
-        mock.simpleMethodWithArgument("7");
-        mock.simpleMethodWithArgument("5");
-
-        replay(mock);
-
-        mock.simpleMethodWithArgument("1");
-        mock.simpleMethodWithArgument("2");
-
-        boolean failed = false;
-        try {
-            mock.simpleMethodWithArgument("4");
-        } catch (AssertionError e) {
-            failed = true;
-        }
-        if (!failed) {
-            fail();
-        }
-
-        mock.simpleMethodWithArgument("3");
-        mock.simpleMethodWithArgument("4");
-        mock.simpleMethodWithArgument("5");
-        mock.simpleMethodWithArgument("6");
-        mock.simpleMethodWithArgument("7");
-
-        verify(mock);
-
-    }
-
-    @Test
-    public void resumeIfFailure() {
-        IMethods mock = createMock(IMethods.class);
-        expect(mock.oneArg(true)).andReturn("foo").anyTimes();
-        replay(mock);
-
-        mock.oneArg(true);
-
-        try {
-            mock.simpleMethod();
-        } catch (AssertionError error) {
-        }
-
-        mock.oneArg(true);
-
-        verify(mock);
-    }
-
-    @Test
-    public void defaultResetToNice() {
-        IMethods mock = createMock(IMethods.class);
-
-        expect(mock.oneArg(true)).andReturn("foo");
-        replay(mock);
-
-        resetToNice(mock);
-
-        replay(mock);
-
-        assertNull(mock.oneArg(true));
-
-        verify(mock);
-    }
-
-    @Test
-    public void strictResetToDefault() {
-        IMethods mock = createStrictMock(IMethods.class);
-
-        expect(mock.oneArg(true)).andReturn("foo");
-        expect(mock.oneArg(false)).andReturn("foo");
-        
-        replay(mock);
-
-        resetToDefault(mock);
-        
-        expect(mock.oneArg(false)).andReturn("foo");
-        expect(mock.oneArg(true)).andReturn("foo");
-
-        replay(mock);
-        
-        assertEquals("foo", mock.oneArg(false));
-        assertEquals("foo", mock.oneArg(true));
-
-        verify(mock);
-    }
-
-    @Test
-    public void niceToStrict() {
-        IMethods mock = createNiceMock(IMethods.class);
-
-        expect(mock.oneArg(false)).andReturn("foo");
-        
-        replay(mock);
-        
-        assertNull(mock.oneArg(true));
-
-        resetToStrict(mock);
-        
-        expect(mock.oneArg(false)).andReturn("foo");
-        expect(mock.oneArg(true)).andReturn("foo");
-
-        replay(mock);
-        
-        try {
-            mock.oneArg(true);
-            fail();
-        }
-        catch(AssertionError e) {            
-        }
-        
-        assertEquals("foo", mock.oneArg(false));
-        assertEquals("foo", mock.oneArg(true));
-
-        verify(mock);
-    }
-}
+/**
+ * Copyright 2001-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.easymock.tests2;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.easymock.tests.IMethods;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author OFFIS, Tammo Freese
+ */
+public class UsageTest {
+
+    IMethods mock;
+
+    @Before
+    public void setup() {
+        mock = createMock(IMethods.class);
+    }
+
+    @Test
+    public void exactCallCountByLastCall() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2");
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+
+        boolean failed = false;
+        try {
+            mock.oneArg(false);
+        } catch (final AssertionError expected) {
+            failed = true;
+        }
+        if (!failed)
+            fail("expected AssertionError");
+    }
+
+    @Test
+    public void openCallCountByLastCall() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2").atLeastOnce();
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+    }
+
+    @Test
+    public void exactCallCountByLastThrowable() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2").andThrow(
+                new IndexOutOfBoundsException());
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+
+        try {
+            mock.oneArg(false);
+            fail();
+        } catch (final IndexOutOfBoundsException expected) {
+        }
+
+        boolean failed = true;
+        try {
+            mock.oneArg(false);
+            failed = false;
+        } catch (final AssertionError expected) {
+        }
+        if (!failed)
+            fail("expected AssertionError");
+    }
+
+    @Test
+    public void openCallCountByLastThrowable() {
+        expect(mock.oneArg(false)).andReturn("Test").andReturn("Test2").andThrow(
+                new IndexOutOfBoundsException()).atLeastOnce();
+
+        replay(mock);
+
+        assertEquals("Test", mock.oneArg(false));
+        assertEquals("Test2", mock.oneArg(false));
+
+        try {
+            mock.oneArg(false);
+        } catch (final IndexOutOfBoundsException expected) {
+        }
+        try {
+            mock.oneArg(false);
+        } catch (final IndexOutOfBoundsException expected) {
+        }
+    }
+
+    @Test
+    public void moreThanOneArgument() {
+        expect(mock.threeArgumentMethod(1, "2", "3")).andReturn("Test").times(2);
+
+        replay(mock);
+
+        assertEquals("Test", mock.threeArgumentMethod(1, "2", "3"));
+
+        boolean failed = true;
+        try {
+            verify(mock);
+            failed = false;
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Expectation failure on verify:"
+                    + "\n    IMethods.threeArgumentMethod(1, \"2\", \"3\"): expected: 2, actual: 1", expected
+                    .getMessage());
+        }
+        if (!failed) {
+            fail("exception expected");
+        }
+    }
+
+    @Test
+    public void wrongArguments() {
+        mock.simpleMethodWithArgument("3");
+        replay(mock);
+
+        try {
+            mock.simpleMethodWithArgument("5");
+            fail();
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.simpleMethodWithArgument(\"5\"):"
+                    + "\n    IMethods.simpleMethodWithArgument(\"3\"): expected: 1, actual: 0", expected
+                    .getMessage());
+        }
+
+    }
+
+    @Test
+    public void summarizeSameObjectArguments() {
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("3");
+        replay(mock);
+
+        try {
+            mock.simpleMethodWithArgument("5");
+            fail();
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.simpleMethodWithArgument(\"5\"):"
+                    + "\n    IMethods.simpleMethodWithArgument(\"3\"): expected: 2, actual: 0", expected
+                    .getMessage());
+        }
+
+    }
+
+    @Test
+    public void argumentsOrdered() {
+        mock.simpleMethodWithArgument("4");
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("2");
+        mock.simpleMethodWithArgument("0");
+        mock.simpleMethodWithArgument("1");
+        replay(mock);
+
+        try {
+            mock.simpleMethodWithArgument("5");
+            fail("exception expected");
+        } catch (final AssertionError expected) {
+            assertEquals("\n  Unexpected method call IMethods.simpleMethodWithArgument(\"5\"):"
+                    + "\n    IMethods.simpleMethodWithArgument(\"4\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"3\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"2\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"0\"): expected: 1, actual: 0"
+                    + "\n    IMethods.simpleMethodWithArgument(\"1\"): expected: 1, actual: 0", expected
+                    .getMessage());
+        }
+
+    }
+
+    @Test
+    public void mixingOrderedAndUnordered() {
+        mock.simpleMethodWithArgument("2");
+        mock.simpleMethodWithArgument("1");
+        checkOrder(mock, true);
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("4");
+        checkOrder(mock, false);
+        mock.simpleMethodWithArgument("6");
+        mock.simpleMethodWithArgument("7");
+        mock.simpleMethodWithArgument("5");
+
+        replay(mock);
+
+        mock.simpleMethodWithArgument("1");
+        mock.simpleMethodWithArgument("2");
+
+        boolean failed = false;
+        try {
+            mock.simpleMethodWithArgument("4");
+        } catch (final AssertionError e) {
+            failed = true;
+        }
+        if (!failed) {
+            fail();
+        }
+
+        mock.simpleMethodWithArgument("3");
+        mock.simpleMethodWithArgument("4");
+        mock.simpleMethodWithArgument("5");
+        mock.simpleMethodWithArgument("6");
+        mock.simpleMethodWithArgument("7");
+
+        verify(mock);
+
+    }
+
+    @Test
+    public void resumeIfFailure() {
+        final IMethods mock = createMock(IMethods.class);
+        expect(mock.oneArg(true)).andReturn("foo").anyTimes();
+        replay(mock);
+
+        mock.oneArg(true);
+
+        try {
+            mock.simpleMethod();
+        } catch (final AssertionError error) {
+        }
+
+        mock.oneArg(true);
+
+        verify(mock);
+    }
+
+    @Test
+    public void defaultResetToNice() {
+        final IMethods mock = createMock(IMethods.class);
+
+        expect(mock.oneArg(true)).andReturn("foo");
+        replay(mock);
+
+        resetToNice(mock);
+
+        replay(mock);
+
+        assertNull(mock.oneArg(true));
+
+        verify(mock);
+    }
+
+    @Test
+    public void strictResetToDefault() {
+        final IMethods mock = createStrictMock(IMethods.class);
+
+        expect(mock.oneArg(true)).andReturn("foo");
+        expect(mock.oneArg(false)).andReturn("foo");
+
+        replay(mock);
+
+        resetToDefault(mock);
+
+        expect(mock.oneArg(false)).andReturn("foo");
+        expect(mock.oneArg(true)).andReturn("foo");
+
+        replay(mock);
+
+        assertEquals("foo", mock.oneArg(false));
+        assertEquals("foo", mock.oneArg(true));
+
+        verify(mock);
+    }
+
+    @Test
+    public void niceToStrict() {
+        final IMethods mock = createNiceMock(IMethods.class);
+
+        expect(mock.oneArg(false)).andReturn("foo");
+
+        replay(mock);
+
+        assertNull(mock.oneArg(true));
+
+        resetToStrict(mock);
+
+        expect(mock.oneArg(false)).andReturn("foo");
+        expect(mock.oneArg(true)).andReturn("foo");
+
+        replay(mock);
+
+        try {
+            mock.oneArg(true);
+            fail();
+        } catch (final AssertionError e) {
+        }
+
+        assertEquals("foo", mock.oneArg(false));
+        assertEquals("foo", mock.oneArg(true));
+
+        verify(mock);
+    }
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/easymock.git



More information about the pkg-java-commits mailing list