The toolkit is provided as a versioned zip file that
contains everything (jars, sources, documentation, and build files), and also as a set of Maven artifacts deployed
to the Maven Central repository (under
"<groupId>com.googlecode.jmockit</groupId>").
The mocking APIs and other tools are documented through a tutorial,
API documentation, and several
sample test suites.
Follow these instructions to start using JMockit:
jmockit" directory containing the library jars, source files, samples,
API javadocs, and additional documentation.
If you want to build the JMockit project itself using Ant, then you should also download and unpack (to the
"jmockit" dir) the jmockit-libs.zip file.
To build with Maven, simply use the "jmockit/main/pom.xml" file from the full distribution, or from a
SVN checkout.
jmockit.jar to your classpath (in your Java IDE project, Ant
build file, and so on, as required).
jmockit.jar appears before the JUnit jar file in the classpath.
attach" native library.)
-javaagent:<proper path>/jmockit.jar" (with the proper absolute
or relative path to jmockit.jar) is passed as an initialization parameter to the JVM when
running tests.
This standard parameter causes the JVM to load the "Java agent" that JMockit uses internally for bytecode
instrumentation.
You may have to use it even on a newer JDK 1.6+, if its
Attach API
implementation doesn't work with JMockit for some reason; typically, this happens with the IBM JDK 1.6.
jmockit.jar
file.
API documentation in HTML is also available in the "jmockit/www/javadoc" directory, as well as
on-line.
For instructions on the use of JMockit from an Ant build script, see the relevant section in the JMockit Tutorial. For Maven, see this section.
The JMockit mocking APIs can be used in tests written with any of the popular testing frameworks:
JUnit 4 (version 4.5 or newer, including support for junit.framework.TestCase) and TestNG
(version 5.14 or newer).
Lets now see how mocking is done with the available JMockit APIs, which are all imported from the
mockit package.
In a test class, declare a mock field of the type you wish to mock, annotating it with a JMockit annotation
such as @Mocked or @Injectable.
When mocking a class, the latter annotation means that only the instance assigned to the mock field will
have mock behavior; if it is not applied, all instances of the mocked class will be mocked by default.
import org.junit.*;
import mockit.*;
public class MyFirstJMockitTest
{
// Mocked instances (rather than conventional "mock objects") will be
// automatically created and assigned to annotated mock fields:
@Mocked Collaborator mock1; // all current and future instances are mocked
@Injectable AnotherDependency anotherMock; // only one particular instance is mocked
@Test
public void myFirstTestMethod()
{
// Any mock field can be used here or in any other test method of the class.
}
@Test
public void testMethodWithMockParameter(@Mocked YetAnotherDependency testSpecificMock)
{
...
}
...
}
The template test class above shows something unusual: the second test method declares a parameter!
Normally, JUnit/TestNG test methods are not allowed to have parameters.
When using JMockit, however, such mock parameters are allowed and quite useful.
In fact, it's best to use mock fields of the test class only when the mocked types are needed by most or all tests in
the class. Otherwise, mock parameters (or local mock fields, which we introduce later) with scope limited to
a single test are preferred.
JMockit will always take care of instantiating the mocked type and either assigning the instance to the mock field
(provided the field is not final) or passing it as an argument when the test method is invoked by the
test runner.
The following template shows the basic structure of a JMockit test method, when using the Expectations & Verifications API for behavior-based testing:
@Test
public void aTestMethod(<any number of mock parameters>)
{
// Record phase: expectations on mocks are recorded; empty if there is nothing to record.
// Replay phase: invocations on mocks are "replayed"; here the code under test is exercised.
// Verify phase: expectations on mocks are verified; empty if there is nothing to verify.
}
Each test method can be divided in three execution phases. First, one or more invocations on mocked types/instances are recorded. (In fact, it is perfectly valid to not record any invocation at all - more on this later.) Second, the production code/class/unit which our test method is supposed to test is exercised, typically with a call to a single tested method. Any invocations to mocked methods/constructors that were previously recorded will now have a chance to be replayed. Third, the test method can explicitly verify that specific invocations to mocked methods/constructors actually happened (or not) during replay. Again, it is perfectly valid for this phase to be empty, with no explicit verifications (but with implicit, automatic, verifications - otherwise no behavior would be tested). Note that we say "mocked methods/constructors". The mocking API handles mocked methods (of all kinds) and constructors in the exact same way: to record or verify expectations on them, you simply invoke them during the corresponding test execution phase.
In the "record" phase of a test, we can write one or more expectation blocks, inside which invocations to mocked types/instances are recorded.
@Test
public void aTestMethod()
{
new NonStrictExpectations() {
@Mocked MyCollaborator mock; // a "local" mock field
{
mock.getData(); result = "my test data";
mock.doSomething(anyInt, "some expected value", anyString); times = 1;
}
};
// In the replay phase, the tested method would call the "getData" and "doSomething"
// methods on a "MyCollaborator" instance.
...
// In the verify phase, we may optionally verify expected invocations to "MyCollaborator"
// objects.
...
}
There are two classes that can be used to define "expectation blocks": Expectations
and NonStrictExpectations.
The difference is in the default behavior for the recorded expectations.
In the first case, all expectations associated to mocked types used in the block will be strict by default,
meaning that the invocations are expected to occur during the replay phase in the same order as they were
recorded, and that invocations not recorded are expected to not occur.
In the second case, expectations are always non-strict, meaning that the invocations to mocked types,
whether recorded or not, are allowed to occur in any order and in any number, including not at all.
There is also a @NonStrict annotation which can be applied to mock fields/parameters,
to force only non-strict expectations on them, even inside an otherwise strict
Expectations block.
You may be wondering what are those field assignments in the example test above.
This is indeed something that you won't see in any other mocking API. That said, it should feel very intuitive once
the semantics are known:
the result field takes the desired return value for the preceding invocation, while
times takes the number of times the preceding invocation is allowed and expected to occur.
(There is also a minTimes and a maxTimes field.)
The result field also accepts a Throwable instance, which would cause
the corresponding invocation in the replay phase to throw the specified exception or error.
Another interesting feature of the API is its support for argument matching constraints.
The test above uses some of the special "any" fields, such as anyString,
anyDouble, and so on.
The API also provides a set of "with(...)" methods, such as withNotNull(),
withSameInstance(T), etc.
Arbitrary user-defined matchers can be provided through a call to the with(Delegate) method.
Finally, it should be noted that, differently from most other mocking APIs, JMockit does not require a
matcher for every parameter;
any subset of parameters can have matching constraints, with actual values or objects being provided for the
remaining ones.
When one or more types get mocked non-strictly in a test, we often end up with a non-empty verification phase. (If, on the other hand, all mocked types used in the test have only strict expectations, then all invocations get implicitly and automatically verified at the end of the test, with no explicit verify phase.) To explicitly verify invocations to non-strict mocked types/instances, we can write one or more verification blocks in the test. This allows us to make sure that the invocations we care about actually occurred during the replay phase.
@Test
public void aTestMethod(@Injectable final MyCollaborator mock)
{
// Non-strict expectations are recorded, or perhaps there are no expectation blocks at all.
...
// Code under test is exercised.
...
new Verifications() {{
// If no new instance of the mocked class should have been created with the
// no-args constructor, we can verify it:
new MyCollaborator(); times = 0;
// Here we verify that the "MyCollaborator#doSomething()" method was executed at least once:
mock.doSomething();
// Another verification, which must have occurred no more than three times:
mock.someOtherMethod(anyBoolean, any, withInstanceOf(Xyz.class)); maxTimes = 3;
}};
}
The Verifications API is quite rich and flexible. Besides the Verifications class
shown above, which allows some invocations to be verified regardless of their order of execution, we have the
VerificationsInOrder, FullVerifications, and
FullVerificationsInOrder subclasses.
The "InOrder" suffix simply means that the relative order of the invocations appearing inside the verification block
will have to match the actual order of execution of corresponding invocations during replay.
The "Full" prefix means that all invocations that occurred during replay must be accounted for (verified) inside
the verification block (excluding those which are verified implicitly, if any).
Sometimes you are more interested in checking the argument values passed to a mocked collaborator, instead of
checking that the invocation to the collaborator was made from the client/tested method.
Of course, you can check argument values through a recorded or verified expectation, but it becomes more
difficult when those values are complex.
In such cases it may be easier to use the MockUp<T> generic class, as the next test
shows.
@Test
public void stateBasedTestMethod()
{
new MockUp<MyCollaborator>() {
@Mock(invocations = 1) // (the invocation count constraint is optional)
boolean doSomething(int n, String s, ComplexData otherData)
{
assertEquals(1, n);
assertNotNull(otherData);
...
// Return (if non-void) or throw the result we want to produce for
// this invocation of the mocked method:
return otherData.isValid();
}
// Other mock or regular methods...
};
// Exercise the code under test normally; calls to MyCollaborator#doSomething will execute
// the mock method above; if more or less than one such invocation occurs, the test fails.
...
}
The @Mock annotation marks those methods in the mock-up class which are
meant to provide mock/stub implementations for the corresponding methods (of the same signature) in the mocked class.
If no invocation count constraint is specified through attributes of the @Mock
annotation, then any number (including zero) of invocations will be allowed.
A MockUp<T> subclass can also be used as a general-purpose fake implementation
for the indicated type "T" (including final classes, classes with static
methods, etc.).
Such implementations can even be applied globally, by setting the "jmockit-mocks" system property or
providing a "jmockit.properties" configuration file.
The examples above give only a brief overview of the available mocking APIs. There is more.
The JMockit Tutorial contains an extensive discussion of nearly all methods, fields,
annotations, etc., with many examples.
The API documentation provides a detailed specification for all elements
of the mocking APIs.
Finally, there are hundreds of JUnit sample tests available under the
"jmockit/samples" folder, which use nearly everything that is available in the APIs.