Update Sep 2019: The only mocking framework supported (by default) by Spring Boot is Mockito. If you use Spring, the answer is quite obvious.
I'd say the competition is between JMockit and PowerMock, then Mockito.
I'd leave "plain" jMock and EasyMock because they use only proxy & CGLIB and do not use Java 5 instrumentation like the newer frameworks.
jMock also didn't have a stable release for over 4 years. jMock 2.6.0 required 2 years to go from RC1 to RC2, and then another 2 years before it actually got released.
Regarding Proxy & CGLIB vs instrumentation:
(EasyMock and jMock) are based on java.lang.reflect.Proxy,
which requires an interface to be
implemented. Additionally, they
support the creation of mock objects
for classes through CGLIB subclass
generation. Because of that, said
classes cannot be final and only
overridable instance methods can be
mocked. Most importantly, however,
when using these tools the
dependencies of code under test (that
is, the objects of other classes on
which a given class under test
depends) must be controlled by the
tests, so that mock instances can be
passed to the clients of those
dependencies. Therefore, dependencies
can't simply be instantiated with the
new operator in a client class for
which we want to write unit tests.
Ultimately, the technical limitations
of conventional mocking tools impose
the following design restrictions on
production code:
- Each class which may need to be mocked in a test must either implement
a separate interface or not be final.
- The dependencies of each class to be tested must either be obtained
through configurable instance creation
methods (factories or a Service
Locator), or be exposed for dependency
injection. Otherwise, unit tests won't
be able to pass mock implementations
of dependencies to the unit under
test.
- Since only instance methods can be mocked, classes to be unit tested
cannot call any static methods on
their dependencies, nor instantiate
them using any of the constructors.
The above is copied from http://jmockit.org/about.html . Further, it compares between itself (JMockit), PowerMock, and Mockito in several ways:
There are now other mocking tools for
Java which also overcome the
limitations of the conventional ones,
between them PowerMock, jEasyTest, and
MockInject. The one that comes closest
to the feature set of JMockit is
PowerMock, so I will briefly evaluate
it here (besides, the other two are
more limited and don't seem to be
actively developed anymore).
JMockit vs PowerMock
- First of all, PowerMock does not provide a complete API for mocking,
but instead works as an extension to
another tool, which currently can be
EasyMock or Mockito. This is obviously
an advantage for existing users of
those tools.
- JMockit, on the other hand, provides entirely new APIs, although
its main API (Expectations) is similar
to both EasyMock and jMock. While this
creates a longer learning curve, it
also allows JMockit to provide a
simpler, more consistent, and easier
to use API.
- Compared to the JMockit Expectations API, the PowerMock API is
more "low-level", forcing users to
figure out and specify which classes
need to be prepared for testing (with
the @PrepareForTest({ClassA.class,
...}) annotation) and requiring
specific API calls to deal with
various kinds of language constructs
that may be present in the production
code: static methods
(mockStatic(ClassA.class)),
constructors
(suppress(constructor(ClassXyz.class))),
constructor invocations
(expectNew(AClass.class)), partial
mocks (createPartialMock(ClassX.class,
"methodToMock")), etc.
- With JMockit Expectations, all kinds of methods and constructors are
mocked in a purely declarative way,
with partial mocking specified through
regular expressions in the @Mocked
annotation or by simply "un-mocking"
the members with no recorded
expectations; that is, the developer
simply declares some shared "mock
fields" for the test class, or some
"local mock fields" and/or "mock
parameters" for individual test
methods (and in this last case the
@Mocked annotation often won't be
needed).
- Some capabilities available in JMockit, such as support for mocking
equals and hashCode, overridden
methods, and others, are currently not
supported in PowerMock. Also, there is
no equivalent to JMockit's ability to
capture instances and mock
implementations of specified base
types as the test executes, without
the test code itself having any
knowledge of the actual implementation
classes.
- PowerMock uses custom class loaders (usually one per test class)
in order to generate modified versions
of the mocked classes. Such heavy use
of custom class loaders can lead to
conflicts with third-party libraries,
hence the need to sometimes use the
@PowerMockIgnore("package.to.be.ignored")
annotation on test classes.
- The mechanism used by JMockit (runtime instrumentation through a
"Java agent") is simpler and safer,
although it does require passing a
"-javaagent" parameter to the JVM when
developing on JDK 1.5; on JDK 1.6+
(which can always be used for
development, even if deploying on an
older version) there is no such
requirement, since JMockit can
transparently load the Java agent on
demand by using the Attach API.
Another recent mocking tool is
Mockito. Although it does not attempt
to overcome the limitations of older
tools (jMock, EasyMock), it does
introduce a new style of behavior
testing with mocks. JMockit also
supports this alternative style,
through the Verifications API.
JMockit vs Mockito
- Mockito relies on explicit calls to its API in order to separate code
between the record (when(...)) and
verify (verify(...)) phases. This
means that any invocation to a mock
object in test code will also require
a call to the mocking API.
Additionally, this will often lead to
repetitive when(...) and
verify(mock)... calls.
- With JMockit, no similar calls exist. Sure, we have the new
NonStrictExpectations() and new
Verifications() constructor calls, but
they occur only once per test
(typically), and are completely
separate from the invocations to
mocked methods and constructors.
- The Mockito API contains several inconsistencies in the syntax used for
invocations to mocked methods. In the
record phase, we have calls like
when(mock.mockedMethod(args))... while
in the verify phase this same call
will be written as
verify(mock).mockedMethod(args).
Notice that in the first case the
invocation to mockedMethod is made
directly on the mock object, while in
the second case it is made on the
object returned by verify(mock).
- JMockit has no such inconsistencies because invocations to
mocked methods are always made
directly on the mocked instances
themselves. (With one exception only:
to match invocations on the same
mocked instance, an onInstance(mock)
call is used, resulting in code like
onInstance(mock).mockedMethod(args);
most tests won't need to use this,
though.)
- Just like other mocking tools which rely on method
chaining/wrapping, Mockito also runs
into inconsistent syntax when stubbing
void methods. For example, you write
when(mockedList.get(1)).thenThrow(new
RuntimeException()); for a non-void
method, and doThrow(new
RuntimeException()).when(mockedList).clear();
for a void one. With JMockit, it's
always the same syntax:
mockedList.clear(); result = new
RuntimeException();.
- Yet another inconsistency occurs in the use of Mockito spies: "mocks"
that allow the real methods to be
executed on the spied instance. For
example, if spy refers to an empty
List, then instead of writing
when(spy.get(0)).thenReturn("foo") you
will need to write
doReturn("foo").when(spy).get(0). With
JMockit, the dynamic mocking feature
provides similar functionality to
spies, but without this issue since
real methods only get executed during
the replay phase.
- In EasyMock and jMock, the first mocking APIs for Java, the focus was
entirely on the recording of expected
invocations of mocked methods, for
mock objects that (by default) do not
allow unexpected invocations. Those
APIs also provide the recording of
allowed invocations for mock objects
that do allow unexpected invocations,
but this was treated as a second-class
feature. Additionally, with these
tools there is no way to explicitly
verify invocations to mocks after the
code under test is exercised. All such
verifications are performed implicitly
and automatically.
- In Mockito (and also in Unitils Mock), the opposite viewpoint is
taken. All invocations to mock objects
that may happen during the test,
whether recorded or not, are allowed,
never expected. Verification is
performed explicitly after the code
under test is exercised, never
automatically.
- Both approaches are too extreme, and consequently less than optimal.
JMockit Expectations & Verifications
is the only API that allows the
developer to seamlessly choose the
best combination of strict (expected
by default) and non-strict (allowed by
default) mock invocations for each
test.
- To be more clear, the Mockito API has the following shortcoming. If you
need to verify that an invocation to a
non-void mocked method happened during
the test, but the test requires a
return value from that method that is
different from the default for the
return type, then the Mockito test
will have duplicate code: a
when(mock.someMethod()).thenReturn(xyz)
call in the record phase, and a
verify(mock).someMethod() in the
verify phase. With JMockit, a strict
expectation can always be recorded,
which won't have to be explicitly
verified. Alternatively, an invocation
count constraint (times = 1) can be
specified for any recorded non-strict
expectation (with Mockito such
constraints can only be specified in a
verify(mock, constraint) call).
- Mockito has poor syntax for verifications in order, and for full
verifications (that is, checking that
all invocations to mock objects are
explicitly verified). In the first
case, an extra object needs to be
created, and calls to verify made on
it: InOrder inOrder = inOrder(mock1,
mock2, ...). In the second case, calls
like verifyNoMoreInteractions(mock) or
verifyZeroInteractions(mock1, mock2)
need to be made.
- With JMockit, you simply write new VerificationsInOrder() or new
FullVerifications() instead of new
Verifications() (or new
FullVerificationsInOrder() to combine
both requirements). No need to specify
which mock objects are involved. No
extra mocking API calls. And as a
bonus, by calling
unverifiedInvocations() inside an
ordered verification block, you can
perform order-related verifications
that are simply impossible in Mockito.
Finally, the JMockit Testing Toolkit
has a wider scope and more ambitious
goals than other mocking toolkits, in
order to provide a complete and
sophisticated developer testing
solution. A good API for mocking, even
without artificial limitations, is not
enough for productive creation of
tests. An IDE-agnostic, easy to use,
and well integrated Code Coverage tool
is also essential, and that's what
JMockit Coverage aims to provide.
Another piece of the developer testing
toolset which will become more useful
as the test suite grows in size is the
ability to incrementally rerun tests
after a localized change to production
code; this is also included in the
Coverage tool.
(granted, the source may be biased, but well...)
I'd say go with JMockit. It's the easiest to use, flexible, and works for pretty much all cases even difficult ones and scenarios when you can't control the class to be tested (or you can't break it due to compatibility reasons etc.).
My experiences with JMockit have been very positive.