views:

12560

answers:

16

What's the best framework for creating mock objects in Java? Why? What are the pros and cons of each framework?

+53  A: 

I've had good success using Mockito.

When I tried learning about JMock and EasyMock, I found the learning curve to be a bit steep (though maybe that's just me).

I like Mockito because of its simple and clean syntax that I was able to grasp pretty quickly. The minimal syntax is designed to support the common cases very well, although the few times I needed to do something more complicated I found what I wanted was supported and easy to grasp.

Here's an (abridged) example from the Mockito homepage:

import static org.mockito.Mockito.*;

List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();

It doesn't get much simpler than that.

The only major downside I can think of is that it won't mock static methods.

Brian Laframboise
Beautiful. For static methods, simply combine Mockito with JMockit and there is practically no class too "legacy" for you to be able to test.
Epaga
I love how when you try to do something you shouldn't (e.g. create mocks inline), you get a very clear explanation of what you did wrong in the exception message.
ripper234
cool!, we love it.
javaloper
+1 for Mockito. Even though nowhere mentioned, it seems heavily inspired by Ruby's Mocha framework (which is great).
Matthias
The only think I don't like about mockito is that you cannot use it for android, other than that is a great framework
MexicanHacker
+6  A: 

We are heavily using EasyMock and EasyMock Class Extension at work and are pretty happy with it. It basically gives you everything you need. Take a look at the documentation, there's a very nice example which shows you all the features of EasyMock.

david
In my question, I was more looking for what you like and dislike about a mock framework. I can find the documentation and read all about it - I want to know what the people who have used it think of it.
Josh Brown
EasyMock only works on Java 5 and above, argh!
matt b
A: 

Another one very easy to use is

http://www.jmock.org/

Alotor
Thanks for the answer, but what I was really looking for was what you like and dislike about it from your experience.
Josh Brown
+2  A: 

I started using mocks through JMock, but eventually transitioned to use EasyMock. EasyMock was just that, --easier-- and provided a syntax that felt more natural. I haven't switched since.

Mike Furtak
+1  A: 

Mockito also provides the option of stubbing methods, matching arguments (like anyInt() and anyString()), verifying the number of invocations (times(3), atLeastOnce(), never()), and more.

I've also found that Mockito is simple and clean.

One thing I don't like about Mockito is that you can't stub static methods.

Josh Brown
This answer is inaccurate. You are not limited to interfaces with jMock. You can mock concrete classes with the ClassImposteriser.
Teflon Ted
You can do exactly same things with EasyMock as well.
Cem Catikkas
I've removed the inaccuracies from my answer.
Josh Brown
+3  A: 

Yes, Mockito is a great framework. I use it together with hamcrest and Google guice to setup my tests.

bibix
+3  A: 

You could also have a look at testing using Groovy. In Groovy you can easily mock Java interfaces using the 'as' operator:

def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest

Apart from this basis functionality Groovy offers a lot more on the mocking front:

http://docs.codehaus.org/display/GROOVY/Groovy+Mocks

p3t0r
+9  A: 

I've been having success with jmockit (http://jmockit.dev.java.net)

It's pretty new, and so it's a bit raw and underdocumented. It uses asm (http://asm.objectweb.org/index.html) to dynamically redefine the class bytecode, so it can mock out all methods including static, private, constructors, and static initializers. For example:

import mockit.Mockit;

...
Mockit.redefineMethods(MyClassWithStaticInit.class,
                       MyReplacementClass.class);
...
class MyReplacementClass {
  public void $init() {...} // replace default constructor
  public static void $clinit{...} // replace static initializer
  public static void myStatic{...} // replace static method
  // etc...
}

It has an Expectations interface allowing record/playback scenarios as well:

import mockit.Expectations;
import org.testng.annotations.Test;

public class ExpecationsTest {
  private MyClass obj;

  @Test
  public void testFoo() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo("foo", false), "bas");
      }
    };

    assert "bas".equals(obj.getFoo("foo", false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(String str, boolean bool) {
      if (bool) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}

The downside is that it requires java 5/6.

Kris Pruden
yes, can really recommend this
Epaga
Just an update: the JMockit project moved to http://code.google.com/p/jmockit. It has evolved A LOT since this post (and still is evolving), and now has extensive documentation.
Rogerio
+1  A: 

I like JMock because you are able to set up expectations. This is totally different from checking if a method was called found in some mock libraries. Using JMock you can write very sofisticated expectations. See the jmock cheat-sheat.

Andrea Francia
+16  A: 

I am the creator of PowerMock so obviously I must recommend that! :-)

PowerMock extends both EasyMock and Mockito with the ability to mock static methods, final and even private methods. The EasyMock support is complete, but the Mockito plugin needs some more work. We are planning to add JMock support as well.

PowerMock is not intended to replace other frameworks, rather it can be used in the tricky situations when other frameworks does't allow mocking. PowerMock also contains other useful features such as suppressing static initializers and constructors.

Jan Kronquist
Looking good, I'll give it a try :)
Peter Perháč
+1  A: 

The best solution to mocking is to have the machine do all the work with automated specification-based testing. For Java, see ScalaCheck and the Reductio framework included in the Functional Java library. With automated specification-based testing frameworks, you supply a specification of the method under test (a property about it that should be true) and the framework generates tests as well as mock objects, automatically.

For example, the following property tests the Math.sqrt method to see if the square root of any positive number n squared is equal to n.

val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }

When you call propSqrt.check(), ScalaCheck generates hundreds of integers and checks your property for each, also automatically making sure that the edge cases are covered well.

Even though ScalaCheck is written in Scala, and requires the Scala Compiler, it's easy to test Java code with it. The Reductio framework in Functional Java is a pure Java implementation of the same concepts.

Apocalisp
+2  A: 

For something a little different, you could use JRuby and Mocha which are combined in JtestR to write tests for your Java code in expressive and succinct Ruby. There are some useful mocking examples with JtestR here. One advantage of this approach is that mocking concrete classes is very straightforward.

floehopper
A: 

Another vote for Mockito. :)

Bruce Li
+1  A: 

There is a comparison for JMock and EasyMock here including codes.

Comptrol
+4  A: 

The JMockit project site contains plenty of comparative information for current mocking toolkits.

In particular, check out the feature comparison matrix, which covers EasyMock/EasyMock CE, jMock, Mockito, Unitils Mock, PowerMock, and of course JMockit. I try to keep it accurate and up-to-date, as much as possible.

Rogerio
+1  A: 

I used JMock early. I've tried Mockito at my last project and liked it. More concise, more cleaner. PowerMock covers all needs which are absent in Mockito, such as mocking a static code, mocking an instance creation, mocking final classes and methods. So I have all I need to perform my work.

Dmitry