JDave is a framework which provides an easy way to specify behavior of your classes. Key concepts are specification, which is a container for behaviors. Behaviors define the behavior of a class and they are always expressed within some context. Context defines the setting where particular behavior applies.

For example, we could specify a Stack by first identifying that it has (at least) three interesting states, an empty stack, a full stack and a stack which is neither empty nor full. We would then continue by specifying the behavior of a Stack when it is in these states. The behavior can then be expressed as:

Stack specification
    Empty stack
        - is empty
        - is no longer empty after push
        - ...
    Full stack
        - is full
        - complains on push
        - contains all items
        - ...
    Stack which is neither empty nor full
        - adds to the top when pushing new item
        - ...


A specification is implemented by extending jdave.Specification base class. It is parametrized by the type of object which is created in contexts. Contexts are implemented as public non-static inner classes in the specification class. They do not have to extend any base class or implement any interface. Context can optionally have a public method create() which either returns a context object or is void. If create() methods returns something, it is bound to variables context and be. Context can also optionally have a public void method destroy(). All other public methods in context class are behaviors.

public class StackSpec extends Specification<Stack<?>> {
    public class EmptyStack {
        private Stack<String> stack;

        public Stack<String> create() {
            return stack = new Stack<String>();

        public void someBehavior() {
            // ...

Behaviors are written by doing something to the context object and then specifying some expectations. The expectations are specified using one or more overloaded specify(..., ...) methods.

public class StackSpec extends Specification<Stack<?>> {
    public class EmptyStack {
        // ...

        public void isNoLongerEmptyAfterPush() {
            specify(stack, must.not().be.empty());

Specification base class provides a limited vocabulary to be used for writing expectations. In the above example must is a supplemental word (*) which does nothing. It is used to make expectation more readable. not() triggers following expectations to be negations. be refers to the object which was returned from create() method (be == create()).

(*) does and should can be used too, so these are equivalent:

specify(something, should.equal(...));
specify(something, does.equal(...));
specify(something, must.equal(...));



Expectations are set using specify(..., ...) method.
  • Basic:
    specify(actual.getAge(), must.equal(20));
  • Collection, array, iterator:
    specify(actual, containsInOrder(1, 2, 3));
    specify(actual, containsExactly(1, 2, 3));
  • Exception:
    specify(new Block() {}, must.not().raise(SomeException.class));
    specify(new Block() {}, must.raise(SomeException.class, "message"));
    specify(new Block() {}, must.raiseExactly(SomeException.class));
    specify(new Block() {}, must.not().raiseAnyException());
  • Contract:
    specify(actual, satisfies(new SerializableContract()));
    specify(actual, does.not().satisfy(new CloneableContract()));
  • Hamcrest:
    import static org.hamcrest.Matchers.*;
    specify(person.getAge(), is(greaterThan(30)));
    // Using a shared matcher for all collection elements:
    specify(persons, where(
      new Each<Person>() {{ matches(item.getSurname(), is("Doe")); }}));
    specify(persons, where(
      new Each<Person>() {{ matches(item.getAge(), is(greaterThan(30))); }}));
    specify(persons, where(
      new Each<Person>() {{ matches(item, instanceOf(Person.class)); }}));
    // Using individual matcher for each collection element, fails if
    // number of matchers do not equal with number of elements:
    specify(persons, where(
      new Each<Person>() {{ matches(item.getAge(), is(35), is(31)); }}));


A new Specification and context instance is created before executing each behavior. destroy() method is executed just after each behavior method.
  1. spec = new SomeSpecification();
  2. spec.create();
  3. ctx = SomeContext();
  4. be = ctx.create();
  5. // if exists
  6. [run some behavior]
  7. ctx.destroy(); // if exists
  8. spec.destroy();
  9. skip to 1. if there's more behaviors to be run
It is possible to register a ILifecycleListener in a specification to get notifications about lifecycle events.


Specification class provides expectation methods to compare various collection classes and their friends.
  • containsAll, does.not().containAll
  • The actual collection must contain all given elements. The order of elements is not significant.
  • containsAny, does.not().containAny
  • The actual collection must contain at least one element from given collection.
  • containsExactly, does.not().containExactly
  • The actual collection must contain exactly the same elements as in given collection. The order of elements is not significant.
  • containsInOrder, does.not().containInOrder
  • The actual collection must contain exactly the same elements as in given collection and in same order.
  • containsInPartialOrder, does.not().containInPartialOrder
  • The actual collection can hold other objects, but the objects which are common in both collections must be in same order. The actual collection can also repeat some elements. Example, [1, 2, 2, 3, 4] is in partial order with [1, 2, 3]. See Wikipedia for further information.
Containments can be done for arrays, Collections, Iterators and Iterables.

specify(Arrays.asList(0, 1, 2), containsAll(Arrays.asList(0, 1)));
specify(Arrays.asList(1, 2).iterator(), containsAny(0, 1));
specify(new Object[] { 1, 2 }, does.not().containAny(0, -1)));
specify(new MyIterable(1, 2), containsExactly(2, 1)));
specify(new MyIterable(1, 2), containsInOrder(1, 2)));
specify(Arrays.asList(1, 2, 3), containsInPartialOrder(1, 2)));

Application specific containments can be done by implementing jdave.IContainment interface.

Map containments can be specified using maps(key1, key2, ...).to(value1, value2, ...) construct:

Map<Integer, String> actual =, "foo").map(2, "bar"); 
specify(actual, maps(1, 2).to("foo", "bar"));


Contract enforcements

Some core Java classes impose (or recommend) contracts for classes which implement some interface or override a method. Probably most common is the contract between equals() and hashCode(). The following contract enforcements are provided.
  • EqualsHashCodeContract
  • SerializableContract
  • CloneableContract
  • EqualsComparableContract
Contract is specified using satisfies method. should.not().satisfy can be used if an object should not satisfy a contract.

public void isSerializable() {
    specify(serializable, satisfies(new SerializableContract()));

public void isNotSerializable() {
    specify(nonSerializable, should.not().satisfy(new SerializableContract()));

Application specific contracts can be done by implementing jdave.IContract interface.


Using mocks

JMock 2 is integrated as mocking framework. Please refer to JMock documentation.

Mocks are created with mock method and all mocks are automatically verified after the behaviour method execution. Dummies can be created with dummy method. Dummy is a mock whose all methods are ignored.

JMock Mockery instance can be accessed using specification field mockery. By default, JDave uses imposteriser which allows mocking of concrete classes. This default can be changed with mockery.setImposteriser method.

The final keyword protects classes and methods from being overridden. Sometimes you want to mock a class or a method that has been declared final in a 3rd party library. this is not what final should be protecting against, so jdave-unfinalizer removes these restrictions on mocking.

To load jdave-unfinalizer, and thereby unfinalize classes not in the boot classloader, launch your tests with the following vm parameter:


UnfinalizerAcceptanceSpec demonstrates the mocking of a final class and a final method, both previously impossible.


Extending default vocabulary

Extending the default vocabulary is done by overriding fields should, must and does. Then adding new specify(...) and factory methods which provide the extension. Negation can be extended by overriding not() method.

Let's go through an example which adds following extension to the vocabulary:

specify(a, should.approximate(b));

A possible implementation could be done by extending base Specification and encapsulating the extension there. (Note, the extension can also be done as static methods if inheritance is too cumbersome. The methods can then be statically imported to specification which needs them.)

public abstract class ExtendedSpecification<T> extends Specification<T> {
    protected ExtendedSpecification<T> should = this;
    protected ExtendedSpecification<T> does = this;
    protected ExtendedSpecification<T> must = this;
    public void specify(double actual, Approximation approximation) {
    public Approximation approximate(double expected) {
        return new Approximation(expected);

class Approximation {
    private final double expected;

    Approximation(double expected) {
        this.expected = expected;        
    public void approximate(double actual) {
        if (Math.abs(actual - expected) > 0.01) {
            throw new ExpectationFailedException(actual + 
                " is not an approximation of " + expected);

To use the extension simply extend the specification from ExtendedSpecification. See a complete example which supports not() too below:

[usage of extension]

Injecting values into fields

InjectionSupport can be used to inject values into specification (or any other object) fields. This is often used for instance to inject Spring managed beans into specification.


Thread local isolation

Some contexts set thread local variables. This may cause following behaviors to fail if they depend on initial thread local state. Thread locals can be isolated for all behavior methods of current specification by overriding the method Specification.needsThreadLocalIsolation() and returning true. Then a fresh new thread is created for all methods in the specification.


Specifications can be grouped by tagging them with @Group annotation. The annotation takes an array of group names as an argument:

@Group({ "slow", "database" })
public class MySpecification extends Specification<Foo> {

The tagged specifications can then be run with suite runners:

@Groups(include={ "slow" })
public class SuiteForSlowSpecs {

@Groups(include={ Groups.ALL }, exclude={ "slow" })
public class SuiteForNonSlowSpecs {


Report generation can be activated by setting system property Possible values are txt or xml. Use a space limited list to generate dox in multiple formats simultaneously. The target directory is configured by setting system property (default is target/jdave). Sample report generated with txt format:

Empty stack
  - is empty
  - is no longer empty after push

Full stack
  - is full
  - complains on push
  - contains all items
Stack which is neither empty nor full
  - adds to the top when sent push

Generated XML files can be converted to HTML report using XSL styleheet. Install Saxon 8 (or some other XSLT 2.0 compliant processor). Then download specdox.xsl and to a same directory. Process styleseet by running the script: [/path/to/spec/xml/dir/]
Sample HTML report:

Specdox can be generated using a maven plugin too (note, it is required to activate specdox generation to generate xml format The generated HTML will be added to maven reports when generating the site with 'mvn site'. The generated docs will have source xrefs if used with maven-jxr-plugin:


See a sample pom.xml for how to configure specdox as part of a maven build.