JMockit is a class loader remapping toolkit that you can use to replace your dependency classes by remapping them to your desired behavior when unit testing. Under the hood, JMockit uses Java instrumentation API to make direct byte code modifications at runtime.

JMockit framework abstracts this complex capability with its comprehsive APIs to allow engineers to mock interfaces, classes, enums, fields, methods, constructors, and accessors from public, private, protected, static, and final.

Finally, I’d like to point out that JMockit syntax is similar to a DSL (domain specific language) that users need to be familiar with.

I’ll be blogging the following important concepts in an order easier to learn and help answer questions. Hope this will help you too.

@Mocked

public class LoginServiceTest {
    @Mocked UserAccount account;

@Mocked is the most commonly used annotation in JMockit. In the example above, UserAcount instance, “account” is annotated with Mocked. What does this really mean, i.e. What is mocked for UserAccount instance?

  • All UserAccount methods (whether it is private/final/abstract/protected/static and constructors) and all its non-static initializers and non-static fields assignment (e.g. constructors)
  • All of UserAccount super classes (if any) up to but not including java.lang.Object will be mocked recursively.

Tip: To mock static initializers, you have to use @Mocked(stubOutClassInitialization=true). By default, it is false. See Part 2 for an example.

Expectations

When we are unit testing a class, we want it to run reliably, repeatedly and fast. Typically, our class under test will depend on other classes/packages/jars that might be unreliable, expensive to setup/run, or are slow to response. Hence, we need a means to specify the behavior of these external APIs and JMockit provides Expectations to do just that.

   @Mocked UserAccount account;
   @Test
   public void login_3passwordMismatches_shouldRevokeAccount() throws Exception
    {
        new Expectations() {
            {
                account.passwordMatches(anyString); result = false; minTimes = 3;
                account.setRevoked(true);
            }
        };
        for (int i = 0; i < 3; i++) {
            service.login("john", "incorrect_password");
        }
    }

More examples using Expectations

Expectations examples Return result(s) What matches
Constructor
new UserAccount(anyInt);
minTimes = 1; maxTimes = 2;
void new UserAccount(1);
new UserAccount(2);
Method call
account.passwordMatches(anyString);
result = new Exception(); times = 1;
Exception instance @Mock or @Injectable account
Mocked instance
onInstance(account).passwordMatches(anyString);
returns(false, true);
1st call = false.
2nd call = true.
@Mock or @Injectable account

Different Types of Expectations

  NonStrictExpectations Expectations StrictExpectations
Checks order No Yes Yes
Checks invocation count No
0 or more invocations unless “times=x” is added
Yes
At least 1 invocation
Yes
Exactly 1 invocation unless “times=x” is specified
Use with Verifications Definitely Recommended Not necessary

Expectation Argument Matches

10 “any” argument/result matchers 16 “with” argument matchers
any withAny (T arg)
anyBoolean withArgThat(Matcher argument Matcher
anyByte withCapture(List valueHolderForInvocations
anyChar withEqual(double value, double delta)
anyDouble withEqual(float value, float delta)
anyFloat withEqual(T arg)
anyInt withInstanceLike(T object)
anyLong withInstanceOf(Class argClass)
anyShort withMatch(T regex)
any String withNotEqual(T arg)
  withNotNull()
  withNull()
  withPrefix(T text)
  withSameInstance(T object)
  withSubstring(T text)
  withSuffix(T text)

This concludes JMockit Part 1 and I’ll cover more topics in the next 2 parts of this JMockit blog -