If you were registered and logged in, you could join this project.
JMockit is open-source software licensed under the MIT License. It is a collection of tools for use in developer testing, that is, tests written by developers using a testing framework such as JUnit or TestNG. The tools rely on the Java 5 SE instrumentation feature (the java.lang.instrument package), internally using the ASM library to modify bytecode at runtime.
There are currently six different components/tools in the JMockit toolkit, which can be used individually, as follows.
JMockit Core consists of a single class with a small set of static methods, which allow arbitrary methods and constructors of any other class to be replaced with mock implementations at runtime.
This facility can be used for writing unit or integration tests, enabling the isolation of code under test from other parts of the codebase. This approach is an alternative to the conventional use of "mock objects" as provided by tools such as EasyMock and jMock.
Both of those tools are based on java.lang.reflect.Proxy, which requires an interface to be implemented. EasyMock has an extension and jMock has a ClassImposteriser class that make it possible to mock concrete classes, by using CGLIB subclass generation. However, the classes to be mocked cannot be final. Most importantly, however, the creation of instances must be controlled, so that a mock object can be passed to client classes (the code under test). Therefore, mocked classes can't simply be instantiated with the new operator in client or test code. In effect, these limitations impose the following design restrictions on production code:
Another difference between JMockit Core and those tools is that its API is very small and simple (5 static methods).
By eliminating those limitations, we get the benefit that no particular design must be followed by code under test. Legacy code can be unit tested without the need for any adaptation. In short, the testability of production code becomes much less of an issue, and developers have more freedom in using Java language features.
JMockit Core depends on the JVM class redefinition mechanism exposed by java.lang.instrument. Therefore, any JUnit/TestNG tests that use it must be run under a Java 5 SE JVM. However, application and test code can still be compiled to older versions of the language.
public class JMockitCoreExampleTest
{
public void testDoOperationAbc() {
Mockit.redefineMethods(DependencyXyz.class, MockDependencyXyz.class);
// ServiceAbc#doOperation(String) instantiates DependencyXyz and calls a method on it
// with the same argument.
Object result = new ServiceAbc().doOperation("test");
assertNotNull(result);
}
public static class MockDependencyXyz
{
public Object doSomething(String value) {
assertEquals("test", value);
return new Object();
}
}
}
While JMockit Core mock creation mechanism relies on coding conventions for determining which methods/constructors in a mock class are actually mocks, JMockit Annotations provides a pair of Java 5 language annotations for that purpose. In addition, constraints on the number of expected invocations for each mock can be provided.
public class JMockitAnnotationsExampleTest
{
public void testDoOperationAbc() {
Mockit.setUpMocks(MockDependencyXyz.class);
// ServiceAbc#doOperation(String) instantiates DependencyXyz and calls a method on it
// with the same argument.
Object result = new ServiceAbc().doOperation("test");
assertNotNull(result);
}
@MockClass(realClass = DependencyXyz.class)
public static class MockDependencyXyz
{
@Mock(invocations = 1)
public Object doSomething(String value) {
assertEquals("test", value);
return new Object();
}
}
}
The approaches to define mocks provided by JMockit Core and JMockit Annotations are both powerful and simple (in terms of a small user API). However, because of the need to write separate classes and methods to define mocks, tests tend to be more lengthy than similar tests written with EasyMock/jMock would be.
JMockit Expectations therefore provide a record/replay model for writing tests, which allows for more succinct tests. In this model, a test begins by setting one or more expectations on the invocations made from code under test to its collaborators. This is the recording phase, when mocks for the collaborators are created according to the expectations set. Then starts the replay phase, when the code under test is exercised, and the invocations that actually are made on the mocked collaborators are dispatched to the corresponding mock methods and constructors. At the end of the replay phase, the expectations are verified for any missing invocations.
Naturally, the JMockit Expectations API allows for expectations to be set on any kind of method invocation (on interfaces, abstract classes, concrete final or non final classes), as well as on class instantiation through any constructors. Even private methods/constructors can have expectations defined, although at the cost of using strings for their names.
public class JMockitExpectationsExampleTest
{
public void testDoOperationAbc()
{
new Expectations(true)
{
DependencyXyz mock;
{
mock.doSomething("test"); returns(new Object());
}
};
// ServiceAbc#doOperation(String) instantiates DependencyXyz and calls a method on it
// with the same argument.
Object result = new ServiceAbc().doOperation("test");
assertNotNull(result);
}
}
Existing OpenSource code coverage tools, such as Cobertura and EMMA are also less than ideal. Specifically, JMockit Coverage introduces the following benefits.
If you have a suite of integration tests that directly or indirectly use the Hibernate 3 APIs, you know those tests can be quite slow and fragile when compared to unit tests, because of their dependence on database access, and on a large and complex ORM library such as Hibernate. The advantages of such tests, on the other hand, are that they are relativelly easier to write (in my experience at least), and actually test a lot more (O/R mapping, HQL query strings, and the actual relational database).
The JMockit Hibernate Emulation component is a fake implementation of the Hibernate 3 Core APIs, which can be installed in place of the real implementation with a simple JVM initialization argument. When those tests run with the emulation in effect, they won't use the O/R mapping information, nor will they access any real database. All persistence operations, including HQL queries, will be executed against the equivalent of an in-memory database.
JMockit AOP supports the application of advice to any method or constructor. The usual types of advice are supported: before, after, and around.
You are viewing a mobilized version of this site...
View original page here