Install Sun JDK 6 on Ubuntu 11.10


Update 2011-12-20: Following up on comments on the post, I added a section on how to  configure the Java Browser Plugin in manual installation

Update 2011-11-25: I added the information regarding the configuration of the JDK as in my previous post  Configuring Java on Kubuntu 10.10


Since Ubuntu 11.10, there is no longer an official package for the Sun/Oracle JDK. The package sun-java6-jdk is no longer officially available.

Method 1: Install a package provided by a PPA

There is a PPA (Personal Package Archives) made available by Roberto Ferramosca. To add this PPA, run the following command from the command line:

    $ sudo add-apt-repository ppa:ferramroberto/java
    $ sudo apt-get update

You can now install the JDK with the following command:

    $ sudo apt-get install sun-java6-jdk

I you’d like to install the JRE or the Java Plugin along with the JDK, use the following:

sudo apt-get install sun-java6-jdk sun-java6-jre sun-java6-plugin sun-java6-fonts

You must now set the Sun JDK as the default. You can see how to achieve this in a previous post Configuring Java on Kubuntu 10.10.

The benefit of this method is that the JDK will be updated when a newer version of the package is made available.

Method 2: Installing the JDK manually

This method consists of downloading the adequate JDK from the Oracle Web site. The file is a bin file, e.g. jdk-6u29-linux-x64.bin

The first step is to create a temporary folder where we’ll download the file.

    $ mkdir -p ~/tmp/jdk-6u29
    $ cd ~/tmp/jdk-6u29

Once downloaded, make the file executable and run it.

    $ chmod +x jdk-6u29-linux-x64.bin
    $ ./jdk-6u29-linux-x64.bin

Now copy the file to the preferred target location, e.g. ~/dev/jdk

    $ mkdir -p ~/dev/jdk
    $ cd ..
    $ mv jdk-6u29 ~/dev/jdk/

Let’s now create a symbolic link so that we can easily update with newer versions in the future.

    $ cd ~/dev/jdk
    $ ln -s jdk-6u29 jdk-6

The next step is to add to the ~/.bashrc the path to our JDK binary files.

    #Use the symbolic link
    export JAVA_HOME="~/dev/jdk/jdk-6"
    export PATH=$PATH:$JAVA_HOME/bin

That’s it.

The benefit of this method is that one can install any version of the JDK (6 or 7). The downside is that one must manually upgrade the JDK.

Manually configuring the browser plugin

To configure the plugin, you need the JRE that comes with the JDK. If you installed the JDK in $JAVA_HOME, the JRE is located in $JAVA_HOME/jre.

Based on some documentation that I found on Oracle Web Site, the solution is simply to create symlinks to the plugin. The plugin can be found in

  • $JAVA_HOME/jre/lib/amd64/libnpjp2.so for 64bit machines
  • $JAVA_HOME/jre/lib/i386/libnpjp2.so for 32bit machines

You can go to http://javatester.org/version.html to check that the plugin works fine.

Configuring the plugin for Firefox

Create a symlink to the plugin

$ sudo ln -s $JAVA_HOME/jre/lib/amd64/libnpjp2.so /usr/lib/firefox-addons/plugins/libnpjp2.so

This shall do the trick.

Configuring the plugin for Chromium

Create a symlink to the plugin

$ sudo ln -s $JAVA_HOME/jre/lib/amd64/libnpjp2.so /usr/lib/chromium-browser/plugins/libnpjp2.so

With Chromium, it is necessary to enable plugins. You can just launch it from the command line once to enable the plugins with the following command

$ chromium-browser --enable-plugins %U

If you now naviate to chrome://plugins/, you shall see something like:

Java – Version: 1.6.0.30
The next generation Java plug-in for Mozilla browsers.
Disable

Activating a default Maven profile defined in settings.xml with other profiles in the pom.xml


In Apache Maven, there are different places to configure profiles:

  • The project pom.xml
  • The user’s settings.xml
  • The installations settings.xml

I wanted every developer to be able to customise the build properties independently of the pom.xml. It is a very bad practice to have everyone modifying the pom.xml locally. One would also argue that it is a very bad practice to have developers customise build properties. That’s a debate for another time 🙂

The profiles that we have are:

  • Development (default)
  • Jenkins (continuous integration)
  • Test
  • Acceptance
  • Production

The profiles define the target environment for the build.

At first, I tried to define a profile as activeByDefault in the settings.xml file while setting the other profiles in the pom.xml not active by default. That did not work at all because in this case the profile defined in the settings.xml is active at any time and overrides other profiles.

The solution that I found was to use a property to activate a profile. The profile defined in the settings.xml is the Development profile. It would be activated by the absence of such a property. Indeed, it would be boring to have to specify a property for most of the builds.

The settings.xml looks like this:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
	  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
			      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <profiles>
    <profile>
      <id>Development</id>
      <activation>
	<property>
	  <name>!env</name><!-- The exclamation mark indicates that the property shall be absent -->
	</property>
      </activation>
      <properties>
	<target.environment>Development</target.environment>
	...
      </properties>
    </profile>
  </profiles>
</settings>

When using the Maven command mvn help:active-profiles, it yields:

The following profiles are active:

 - Development (source: settings.xml)

The development profile is active if the property env is not set using the Maven command line parameter -Denv=xxx.

All the other profiles are defined in the pom.xml:

...
  <profiles>
    <profile>
      <id>Jenkins</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Jenkins</value> <!-- This is the value for that property that will activate the profile -->
	</property>
      </activation>
      <properties>
	<target.environment>ContinuousIntegration</target.environment>
	...
      </properties>
    </profile>
    <profile>
      <id>Test</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Test</value>
	</property>
      </activation>
      <properties>
	<target.environment>Test</target.environment>
	...
      </properties>
    </profile>
    <profile>
      <id>Acceptance</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Acceptance</value>
	</property>
      </activation>
      <properties>
	<target.environment>Acceptance</target.environment>
	...
      </properties>
    </profile>
    <profile>
      <id>Production</id>
      <activation>
	<property>
	  <name>env</name>
	  <value>Jenkins</value>
	</property>
      </activation>
      <properties>
	<target.environment>Production</target.environment>
	...
      </properties>
    </profile>
...

To activate any profile from the pom.xml instead of the Development profile, we just have to pass the env property to the command line. For example:

$ mvn -Denv=Test help:active-profiles

The command above yields the following result:

The following profiles are active:

 - Test (source: pom)

Using resource bundle keys containing dots in a facelet


In order to put some order into our resource bundle with JSF, I wanted to use dots to structure the keys to make them more meaningful. I wanted to use a structure like ScreenName.title=value

We used to use the keys this way

<h:outputText value="#{bundle.title}" />

When I tried to use

<h:outputText value="#{bundle.screen.title}" />

I got an error because JSF interpreted bundle.screen.title as an expression and title was not a method of the String class. To be able to use the dots, I had to change the way to get values from the bundle as follows:

<h:outputText value="#{bundle['screen.title']}" />

A minimal Maven pom.xml to start with


When one create a default Maven application using an archetype, it is rather incomplete by default. The following pom was created using maven-archetype-quickstart:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>shz</groupId>
  <artifactId>foo</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>foo</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

I need to more start with. Indeed, it is necessary to configure a few more things in order to start developing. In this post, I will look at a minimal pom.xml project file for a jar.

Setting the dependencies

I most of the time use JUnit and Mockito to unit test my code, therefore, I add the following dependencies to the pom.xml:

<dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>
</dependencies>

Working around the maven-eclipse-plugin bug

I develop in Eclipse. If I don’t specify which version of the maven-eclipse-plugin to use, I run into the following error:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building aagile 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-eclipse-plugin:2.8:eclipse (default-cli) @ aagile >>>
[INFO]
[INFO] <<< maven-eclipse-plugin:2.8:eclipse (default-cli) @ aagile <<<
[INFO]
[INFO] --- maven-eclipse-plugin:2.8:eclipse (default-cli) @ aagile ---
[INFO] Using Eclipse Workspace: null
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO] Resource directory's path matches an existing source directory. Resources will be merged with the source directory src/main/java
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.387s
[INFO] Finished at: Sat Nov 20 20:55:45 CET 2010
[INFO] Final Memory: 10M/309M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-eclipse-plugin:2.8:eclipse (default-cli) on project aagile: Request to merge when 'filtering' is not identical. Original=source src/main/java: output=null, include=[**/*.java], exclude=[], test=false, filtering=false, merging with=resource src/main/java: output=target/classes, include=[**/*.xml|**/*.properties], exclude=[**/*.java], test=false, filtering=true -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

To fix it, I simply fix the version of the plugin to use as follows:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-eclipse-plugin</artifactId>
      <version>2.6</version>
      <configuration>
        <ajdtVersion>1.6</ajdtVersion>
      </configuration>
    </plugin>
  </plugins>
</build>

Specify the target version of Java

I want to compile my project against Java 6 so that I can use the features of the language. I do that by specifying the target in the maven-compiler-plugin:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.3.1</version>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
      </configuration>
    </plugin>
  </plugins>
</build>

The final pom.xml looks like

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>shz</groupId>
  <artifactId>foo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.5</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <ajdtVersion>1.6</ajdtVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

References

Configuring Java on Kubuntu 10.10


2010/12/25 Update: Added the removal of the OpenJDK and added the installation of the browser plugin

Today, I had to, again, scratch my Kubuntu install and install it over again. I wonder what I did wrong this time :s

Anyway, what’s important is that, by default, Kubuntu 10.10 ships with OpenJDK 6. When I develop, I prefer to use Sun JDK. This post details the steps necessary to configure the Sun JDK on a Kubuntu/Ubuntu Maverick.

If you find any mistake, please tell me so that I can fix it quickly.

1. Add the necessary repository

Sun JDK is not available in the package repositories available out of the box. The packages are available from the Canonical Partner Repository that can be added with the following commands:

sudo add-apt-repository "deb http://archive.canonical.com/ maverick partner"

It is necessary to reload the configuration afterwards using:

sudo apt-get update

2. Install the necessary packages

Once the package repositories are configured, I can now install the JDK packages with:

sudo apt-get install sun-java6-jdk sun-java6-source sun-java6-jre sun-java6-plugin sun-java6-fonts

You can see that I also install the browser plugin as well as the JRE, which the plugin requires.

3. Set Sun JDK as the default JVM

If I execute:

java -version

That yields on my computer:

version "1.6.0_20"
OpenJDK Runtime Environment (IcedTea6 1.9.1) (6b20-1.9.1-1ubuntu3)
OpenJDK 64-Bit Server VM (build 17.0-b16, mixed mode)

I can change the default JVM by executing:

sudo update-alternatives --config java

This command yields:

There are 2 choices for the alternative java (providing /usr/bin/java).
Selection    Path                                      Priority   Status
------------------------------------------------------------
*0           /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061      auto mode
1            /usr/lib/jvm/java-6-openjdk/jre/bin/java   1061      manual mode
2            /usr/lib/jvm/java-6-sun/jre/bin/java       63        manual mode

Press enter to keep the current choice[*], or type selection number:

After I entered 2, the following message appeared:

update-alternatives: using /usr/lib/jvm/java-6-sun/jre/bin/java to provide /usr/bin/java (java) in manual mode.

If I execute again:

java -version

It now yields:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) 64-Bit Server VM (build 17.1-b03, mixed mode)

Voilà, Sun JDK 6 is the default on my system now.

4. Removing OpenJDK

If you like, you can also completely remove OpenJDK from your computer by running:

sudo apt-get remove openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib

If you now run

sudo update-alternatives --config java

it yields:

There are 1 choices for the alternative java (providing /usr/bin/java).
Selection    Path                                  Priority   Status
------------------------------------------------------------
0            /usr/lib/jvm/java-6-sun/jre/bin/java   63        auto mode*
1            /usr/lib/jvm/java-6-sun/jre/bin/java   63        manual mode

Press enter to keep the current choice[*], or type selection number:

5. Testing your browser plugin

If you want to test that the Java plugin is installed properly, you can surf to http://javatester.org/version.html. You will see something akin to:

6. Set JAVA_HOME

I can now set the JAVA_HOME environment variable to allow applications to find where my JDK is installed. I add the following lines in my .bashrc:

export JAVA_HOME=/usr/lib/jvm/java-6-sun
export PATH=$JAVA_HOME/bin:$PATH

Comparing Java Mock Frameworks – Part 2: Creating Mock Objects


Update 2010/10/19:Eventually updated the conclusion section to provide a worthwhile synthesis (hopefully).

Update 2010/10/11: Reviewed the conclusion section not to draw any conclusion just yet.

Update 2010/10/07: Corrected mistakes pointed out by Rogerio Liesenfeld. Thanks Rogerio.

This is the second instalment in the series Comparing Java Mock Frameworks. This time, I will take a look at how the frameworks instantiate test stubs and mock objects as well as their overriding capabilities. The whole series consists of the following posts:

 


At last, I managed to finalise this second instalment. I didn’t think that I would need so so long to make this first comparison. This is quite a lot of reading and trying out. At the end of the day, I hope you’ll find it useful. If there is any mistake in this post, I’m eager to know and to fix it.

 

For this post, I experimented with the frameworks to get a feel for how they addressed the following issues:

  • How can I obtain an instance of a test double?
  • Can instances be used as stubs and mock objects?
  • Are there limitations in terms of what can be test-doubled?
    • Can the framework mock interfaces, abstract classes, concrete classes, final classes?
    • Can the framework mock final and static methods?
  • Do the mock objects return default values for mocked methods?
  • Are mocked objects strict by default (explicit or implicit verification)?
  • What are the main differences between the frameworks?

Remark: I didn’t dive into the details of each framework. It is not my intent to dive into the details of what each framework provides. I hope I didn’t overlook anything worth mentioning. If so, please tell me.

Different Approaches to Mocking

The tested framework fall into two different categories, depending on the way they create the mock objects:

  • Using  proxy: Create a dynamic implementation of a class using the Java reflection API;
    • Allows redefining the public interface of a class;
  • Remapping classes: Remap the class in the class loader using the Java Instrumentation API;
    • Allows mocking objects that are created using the new operator;
    • Allows completely redefining a class;

The limitations of what the different frameworks can mock come from the approach their take.

Mockito (version 1.8.5)

Mockito does not make any difference between mock objects and test stubs. One can obtain a mock object using the Mockito.mock() method as shown below.

// Mock an interface
List testDouble = Mockito.mock(List.class);
// Mock a class
ArrayList testDouble = Mockito.mock(ArrayList.class);

It is also possible to annotate a class variable that shall be mocked. However, the annotation requires that some specific method be called to allow for the injection. The following code snippet extracted from the official documentation illustrates how to use the annotation.

   public class ArticleManagerTest extends SampleBaseTestCase {

       @Mock private ArticleCalculator calculator;
       @Mock private ArticleDatabase database;
       @Mock private UserProvider userProvider;

       private ArticleManager manager;

       @Before public void setup() {
           manager = new ArticleManager(userProvider, database, calculator);
       }
   }

   public class SampleBaseTestCase {

       @Before public void initMocks() {
           MockitoAnnotations.initMocks(this);
       }
   }

Mockito:

  • Mocks interfaces, abstract classes and concrete classes;
  • Cannot mock final classes. It will throw an exception when trying to mock such a class;
  • Does not mock final and static method. Instead, it delegates the call to the real implementation;
  • Returns default values for mocked methods (0, null, false);
  • Mocked objects are not strict by default;

EasyMock (version 3.0)

EasyMock provides three different ways to instantiate mock objects. The method used to instantiate the object will define its behaviour:

  • EasyMock.createMock(): Does not verify the order in which methods are called and throws an AssertionError for all unexpected method calls.
  • EasyMock.createStrictMock(): Verifies the order in which methods are called and throws an AssertionError for all unexpected method calls.
  • EasyMock.createNiceMock(): Does not verify the order in which methods are called and returns appropriate empty values (0,null,false) for all unexpected method calls.

Nice Mocks can be used as stubs whereas Mock and Strict Mock are pure mock objects.

For example, the EasyMock.createMock() method:

// Mock an interface
List testDouble = EasyMock.createMock(List.class);
// Mock a class
ArrayList testdouble = EasyMock.createMock(ArrayList.class)

EasyMock:

  • Mocks interfaces, abstract classes and concrete classes;
  • Cannot mock final classes. It will throw an exception when mocking such a class;
  • Does not mock final and static method. Instead, it delegates the call to the real implementation;
  • Returns default values for mocked methods depending on how the object was created (Mock, Strict Mock and NiceMock);
  • A mock object can also be converted from one type to another: default, nice or strict;
  • The strictness of the mocked objects depends on the way they were created;

Mockachino (version 0.4)

Mockachino  instantiates both stubs and mock objects in the same way. It can mock interfaces and classes using the Mockachino.mock() method:

// Mock an interface
List testDouble = Mockachino.mock(List.class);
// Mock a class
ArrayList testDouble = Mockachino.mock(ArrayList.class);

Mockachino:

  • Mocks interfaces, abstract classes and concrete classes;
  • Cannot mock final classes. It will throw an exception when trying to mock such a class;
  • Does not mock final and static method. Instead, it delegates the call to the real implementation;
  • Returns default values for mocked methods (0, null, false);
  • Mocked objects are not strict by default;

jMock (version 2.5.1)

jMock  instantiates both stubs and mock objects in the same way. It can naturally  mock interfaces using an instance of the Mockery class. The test case class must be annotated be annotated with @RunWith(JMock.class) for JUnit4.

@RunWith(JMock.class)
public class ListTest {
    Mockery context = new JUnit4Mockery();

    @Test
    public void shouldMockInterface() {
        List mockList = context.mock(List.class);
        ...
    }
}

By design, jMock does not naturally mock classes. It is however possible to achieve that using a ClassImposteriser:

@RunWith(JMock.class)
public class ListTest {
    Mockery context = new Mockery() {
        {
            setImposteriser(ClassImposteriser.INSTANCE);
        }
    };

    @Test
    public void shouldMockClass() {
        ArrayList mockList = context.mock(ArrayList.class);
        ...
    }
}

By default mocked objects are strict. It is however possible to change this behaviour by declaring expectations and using either ignoring or allowing. The two are equals and one can choose the method that best expresses the intention.

context.checking(new Expectations() {
    {
        ignoring(aMock); // The invocation is allowed any number of times but does not have to happen.
        allowing(anotherMock); // The invocation is allowed any number of times but does not have to happen.
     }
});

jMock:

  • Mocks interfaces, abstract classes and concrete classes;
  • Cannot mock final classes. It will throw an exception when trying to mock such a class;
  • Does not mock final and static method. Instead, it delegates the call to the real implementation;
  • Returns default values for mocked methods (0, empty String, false, empty array, null);
  • Mocked objects are strict by default;

PowerMock (version 1.4.5)

PowerMock is a framework that builds on either Mockito or EasyMock. It provides additional functionality to the underlying framework.

To use PowerMock with JUnit, you have to use the PowerMock test runner.

The @PrepareForTest annotation is used to tell PowerMock to prepare certain classes for testing (typically final classes, classes with final, private, static or native methods that should be mocked and also classes that should be return a mock object upon instantiation). The code snippet below illustrates how to annotate a test case to use PowerMock.

@RunWith(PowerMockRunner.class)
@PrepareForTest( { MyFinalClassToMock.class, MyClassWithStaticMethodsToMock.class })
public class MyTestCase {
...
}

Once the test case is annotated, you can use your favourite mock framework extension (EsayMock or Mockito).

EasyMock Extension

PowerMock provides EasyMock extensions in the class org.powermock.api.easymock.PowerMock.

    MyClass myClassMock = PowerMock.createMock(MyClass.class); // Mock a class or interface
    PowerMock.mockStatic(MyClassWithStatic.class); // Mock a static class

Remark: Because of some class loader issues in the EasyMock extension, I did not manage to make it work as documented. As I didn’t want to spend much time investigating the issue, I hope it will be fixed soon.

Mockito Extension

PowerMock provides a class called PowerMockito that is used for creating mock objects and initiating verification, and expectations. For example:

   PowerMockito.mockStatic(MyClassWithStatic.class); // Mock a static class

PowerMock:

  • Can mock everything (final classes,final, private, and static methods);
  • Can remove static initializers;
  • Allows mocking without dependency injection (replaces instances even when created using new in the code under test);
  • Returns default values for mocked methods (0, null, false) as do EasyMock and Mockito;
  • Mocked objects are not strict by default when using the Mockito extension and are when using the EasyMock extension;

Unitils (version 3.1)

To make your test case Unitils-enabled, you must either extend the class public class UnitilsJUnit4 , or use the JUnit test runner UnitilsJUnit4TestClassRunner. The following code snippet illustrates both ways.

public class Test_Unitils extends UnitilsJUnit4 {
...
}

@RunWith(UnitilsJUnit4TestClassRunner.class)
public class Test_Unitils {
...
}

Having made the test class Unitils-enabled, mock objects can be automatically created and injected using the Mock type. For example:

public class Test_Unitils extends UnitilsJUnit4 {
   private Mock<MyClass> mock;
}

It is also possible to obtain a mock object programmatically:

public class Test_Unitils extends UnitilsJUnit4 {
   private Mock<MyClass> mock = new MockObject<MyClass>("myClass", MyClass.class, this);
}

Unitils provides some special annotations to allow for dependency injection in a test. Those annotations apply to fields:

  • @TestedObject: indicates the object under test, whose dependencies will be injected;
  • @InjectInto: indicates that the annotated object should be injected into the tested object based on the value of the property attribute;
  • @InjectIntoByType: indicates that the annotated object should be injected into the tested object based on the type of the object;
  • @InjectIntoStatic: indicates that the annotated object should be injected into a static property of the tested object based on the value of the property attribute;
  • @InjectIntoStaticByType: indicates that the annotated object should be injected into a static property of the tested object based on the type of the object;

The following example is excerpted from the official documentation.

public class InvoiceServiceChargeInvoiceTest extends UnitilsJUnit4 {
    @TestedObject
    private InvoiceService invoiceService;

    @InjectIntoByType
    private Mock<PurchaseOrderDAO> purchaseOrderDAO;

    @InjectIntoByType
    private Mock<AccountDAO> accountDAO;

    @Test
    public void chargeInvoice() {
        // define behavior
        purchaseOrderDAO.returns(asList(new PurchaseOrder(30), new PurchaseOrder(50))).getPurchaseOrders(5);

        invoiceService.chargeInvoice(5, "12345");

        // assert behavior
        accountDAO.assertInvoked().withdraw("12345", 80);
    }
}

Unitils:

  • Mocks interfaces, abstract classes and concrete classes;
  • Cannot mock final classes. It will throw an exception when trying to mock such a class;
  • Does not mock final and static method. Instead, it delegates the call to the real implementation;
  • Returns default values for mocked methods (0, null, false);
  • Mocked objects are non-strict by default;

JMockit (version 0.999.2)

JMockit includes two mocking APIs. The first one is for “behaviour-based testing” and is named the “JMockit Expectations & Verifications” API. The second API is for “state-based testing” and is named “JMockit Annotations” API.

JMockit Expectations & Verification API (for behaviour-based verifications)

Mock objects are essentially defined using annotations. By annotating a variable  with @Mocked, JMockit replaces any instantiation of the class in the test fixture with a mocked instance. JMockit also provides the @NonStrict annotation that leads to non strict mock objects, meaning that they will not fail when non pre-recorded methods are called on the object.

Any object annotated with @Mocked is non-strict as long as no expectation “strict” is defined on it, otherwise, it becomes strict.

@Mocked
MyInterface interfaceTestDouble; // This is a non-strict mock object but it will become strict if no strict expectations are defined on it
@Mocked
MyClass classTestDouble; // This is a non-strict mock object but it will become strict if no strict expectations are defined on it
@NonStrict
MyFinalClass finalClassTestDouble; // This is a non-strict mock object

@Test
public void someTest() {
    // All objects are not null as they were injected by JMockit
    interfaceTestDouble.someMethod();
    classTestDouble.someMethod();
    finalClassTestDouble.someMethod();
}

Because JMockit replaces the actual implementation of the mocked class, any instance of the class will be a mock. In the following code, both objects will be mock objects even though one was instantiated from the regular class.

@Mocked
MyClass classTestDouble; // This is a mock object

@Test
public void foo() {
    MyClass myClass = new MyClass(); // This is a mock object as well!!!
}
...
public class AnotherClass{
    private MyClass myClass;
    public AnotherClass() {
        myClass = new MyClass(); // This is a mock object when the instance is created in the scope of the test.
    }
}

It is also possible to obtain a mock object for a given class by declare it as a parameter to the test method. A parameter of a test method is considered, by default, to be a “mock parameter”; it can optionally be annotated with @Mocked and/or @NonStrict.

@Test
public void shouldCreateMockedParameter(AnotherClass anotherClassMock){
    anotherClassMock.doSomething();
}

JMockit:

  • Can mock everything (final classes,final, private, and static methods);
  • Can remove static initializers;
  • Allows mocking without dependency injection (replaces instances even when created using new in the code under test);
  • Returns default values for non-void methods as 0 for primitive integers, empty collections and arrays, and so on;
  • Mock objects defined with @Mocked are non-strict by default. Defining expectations on them makes them strict;

JMockit Annotations API (for stated-based verifications)

Mock objects are used in behaviour-based verifications. Nevertheless, JMockit provides an API that allows for state-based verifications. I present this API for illustrative purposes, because JMockit is the only framework that provides a dedicated API to perform this kind of validations.

The @UsingMocksAndStubs annotation specifies the classes that must be mocked or stubbed out in the test fixture. Using this annotation, classes passed on as parameters to the annotation will be stubs. This annotation allows using a provided implementation of the stub or mock object to use. The list of classes provided to the annotation contains either production classes or mock classes that are annotated with @MockClass.

The following code snippet is excerpted from the official documentation.

@UsingMocksAndStubs({MockDatabase.class, Email.class})
public final class MyBusinessService_AnnotationsAPI_Test
{
   @MockClass(realClass = Database.class, stubs = "<clinit>")
   public static class MockDatabase
   {
      @Mock(invocations = 1)
      public static List<EntityX> find(String ql, Object... args)
      {
         assertNotNull(ql);
         assertTrue(args.length > 0);
         return Arrays.asList(new EntityX(1, "AX5", "someone@somewhere.com"));
      }

      @Mock(maxInvocations = 1)
      public static void persist(Object o) { assertNotNull(o); }
     }
...
}

In the above example, the static initializer of the Database class is also stubbed out, by specifying the special method name “<clinit>”.

There is one more way to mock  classes with JMockit. It consists in defining what is called a mock class, which is a class with methods annotated with @Mock.  The mock methods of the mock class with substitute for the actual implementations in the target class to mock . Here is an example from the official documentation.
This code snippet defines a mock class, with methods that will substitute for real methods of the target class.

   public static class MockLoginContext
   {
      MockLoginContext() {}

      @Mock
      public MockLoginContext(String name, CallbackHandler callbackHandler)
      {
         assertEquals("test", name);
         assertNotNull(callbackHandler);
      }

      @Mock
      public void login() {}

      @Mock
      public Subject getSubject() { return null; }
   }

This code snippet declares the test. The method substitution is performed when calling the Mockit.setUpMock method with the target class and an instance of the mock class.

   @Test
   public void setUpMocksForGivenRealClassWithGivenMockInstance() throws Exception
   {
      Mockit.setUpMock(LoginContext.class, new MockLoginContext());

      // Inside an application class which creates a suitable CallbackHandler:
      new LoginContext("test", callbackHandler).login();

      ...
   }

Current observations

So far, I can sum up the main characteristics of the frameworks in the following categories:

  • Type: Proxy-based or class remap, which determines the extent to which behaviour can be changed in the created objects;
  • Stubbing: Determines whether the framework allows stubbing, with or without extra configuration steps;
  • Default return values: Not all frameworks behave the same with default values for non-void methods;
  • Instances are strict/non-strict by default: Some frameworks make objects strict by default while others don’t and some others allow specifying the strictness. That can have some importance depending on your testing approach;
  • Programmatic creation: The framework provides static methods to create objects;
  • Declarative creation: The framework provides annotations or wrapper types to identify the objects to mock or stub out;
  • Injects dependencies: The framework injects the dependencies of the class under test that are identified as either mock objects or stubs;
  • Replaces instances created using new: The framework does not need that dependencies be injected into the class under test. It can replace instances created using the new keyword;

All the evaluated frameworks are capable of creating both mock objects and stubs. The differences lies in whether or not the frameworks objects are strict or not by default.

The table below summarises the collected information:

Framework Type Stubbing Default return values Instances are strict/non-strict by default Programmatic creation Declarative creation Injects dependencies Replaces instances created using new
Mockito Proxy-based Yes 0, null, false Non-strict Yes Yes No No
EasyMock Proxy-based Yes Strict instances throw exceptions. Non-strict return 0, null, false Depends on the ways the object was created. Type can be changed at runtime Yes No No No
Mockachino Proxy-based Yes 0, null, false Non-strict Yes No No No
jMock Proxy-based Yes 0, empty String, false, empty array, null Strict Yes No No No
PowerMock Class remap Yes 0, null, false Strict with EasyMock and non-strict with Mockito Yes No No Yes
Unitils Proxy-based Yes 0, null, false Non-strict No Yes Yes No
JMockit Class remap Yes 0, empty collections, empty arrays, Non-strict by default No Yes Yes, replaces instances of @Mocked classes Yes

The two different approaches to mocking allow for different kinds of usage. On the one hand, proxy-based framework do not allow mocking certain elements that are present in legacy code. They are of less help if the code under test does not allow for dependency injection for example. On the other hand, frameworks that are based on class remapping allow testing any kind of code. That comes in particularly handy for legacy code.

In what I have seen so far, I like the possibility to annotate the objects that will be mocked and have them injected. It can help write clean test code.

Conclusions

Since I wrote the first installment, I had time to think again about what I want to achieve in this series. Comments on the post also made me realise that I do not want to choose any framework. I just want to put together information that will help me understand each of them. This information will help me, and any one who might find it helpful, choose the most appropriate tool for the job at hand. I believe it is a question of taste. If it weren’t, all frameworks would look the same :-).

On the other hand, I believe that some other points such as the quality of the documentation as well as the easiness to get started with build tools such as Maven for example might be valid criteria. I shall consider those to help choose a framework.

To conclude, I can’ t really draw any conclusion just yet. We will see in the next posts how to actually use the framework to test some code.

Comparing Java Mock Frameworks – Part 1: The Contenders


Update 2010/10/06:  I removed rMock from the list because it hasn’t been maintained for a while. I might take a look at it some other time.

Update 2010/09/24: I removed the comparison of spying capabilities. Indeed, I believe that such frameworks are not intended for state verification but behaviour verification and stubbing only.

This is the first instalment in the series Comparing Java Mock Frameworks. Here, I present the frameworks that I intend to compare. The whole series consists of the following posts:


Since a while ago, I wanted to line up the major mock frameworks in Java. I am used to Mockito, which I must say I utilize a lot when I have to deal with Test Doubles.

 

I must confess that I very often use a mock framework instead of writing my own test doubles, even in trivial cases. I find it quite handy because, I don’t have to care about those mocks if I later change the interface of the mocked class. Others prefer writing their own mocks in many cases.

I use mock frameworks when I need to impersonate a class for the purpose of testing the behaviour of the class under test. I mostly follow the following patterns:

  • Test Stub: I need to replace a class in order to return values when the class under test calls some methods on the object. I can also use the test stub to throw an exception to test error handling in the class under test.
  • Mock Object: I need to replace a class in order to verify how the class under test interacts with the mock object.

In a mini-series of posts, I will compare mock frameworks for Java to determine which ones best suits me. Here is the list of the different ways I will use them for the comparison:

Instantiation and overriding
  • Obtaining a test double for an interface
  • Obtaining a test double for a class
  • Obtaining a test double for a final class
  • Overriding of final methods in a test double
  • Overriding of static methods in a test double
Test Stubs
  • Returning a single value
  • Returning multiple values orderly
  • Throwing an exception in a non-void method
  • Throwing an exception in a void method
Mock Objects
  • Verify the number of invocations of a method
  • Verify the order of invocations of a method
  • Verify the arguments of an invocation of a method
Fluency of the API
  • The closer to natural language, the better
  • Ease of set up
Specifics Features that make the framework stand out of the crowd

Here are the frameworks that I will compare:

Framework URL
Mockito http://mockito.org/
EasyMock http://easymock.org/
Mockachino http://code.google.com/p/mockachino/
PowerMock http://code.google.com/p/powermock/
jMock http://www.jmock.org/
JMockit http://code.google.com/p/jmockit/
Unitils http://unitils.sourceforge.net/

I will evaluate the frameworks based on my needs. I won’t claim that everyone should, from now on, use the framework I’ll choose 🙂

References:

%d bloggers like this: