Posts Tagged JMock

Tour de Mock 2: JMock

The next mocking API to consider is one that I have used for years, JMock, specifically JMock 2 (for a discussion of JMock 1 usage, please see my older posting “Are You Mocking Me?“). JMock uses a more Domain Specific Language approach to mocking that is very flexible and very expressive, though it can be a bit daunting to someone who’s never used it before.

One of the first things you will notice about the test in the EmailListServlet_JMockTest is that it uses the @RunWith annotation provided by JUnit. This annotation tells JUnit to use a test runner other than the default. In this case, JMock provides a test runner to simplify use of its Mockery construct (you will see it as one of the instance variables). The Mockery is used to create and manage the mocking system. Using the JMock runner allows JUnit to handle the mockery verification step after each test so that you don’t have to do it yourself. You may also notice that I have defined a constructor for this test to set the “imposteriser” (mock creator) used. Since we have both interfaces and classes to mock, the “legacy” imposteriser must be used.

1
2
3
4
5
6
7
8
@RunWith(JMock.class)
public class EmailListServlet_JMockTest {
    private Mockery mockery = new JUnit4Mockery();

    public EmailListServlet_JMockTest(){
        mockery.setImposteriser(ClassImposteriser.INSTANCE);
    }
}

The @Before method in this example is a bit more complex than that of the Spring mocking example, since you have to do a bit more of the binding work yourself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Before
public void before() throws ServletException {
    this.emailListService = mockery.mock(EmailListService.class);

    final ServletConfig servletConfig = mockery.mock(ServletConfig.class);
    mockery.checking(new Expectations(){
        {
            final ServletContext servletContext = mockery.mock(ServletContext.class);
            one(servletConfig).getServletContext(); will(returnValue(servletContext));
            one(servletContext).getAttribute(EmailListService.KEY); will(returnValue(emailListService));
        }
    });

    this.servlet = new EmailListServlet();
    servlet.init(servletConfig);

    this.request = mockery.mock(HttpServletRequest.class);
    this.response = mockery.mock(HttpServletResponse.class);
}

The mockery.checking() method is one of the most used constructs in mocking with JMock. It allows you to provide your test expectations. In this case you can see that we are expecting one call to servletConfig.getServletContext(), which will return the mock ServletContext we have created. We are also expecting one call to the getAttribute() method of the mocked servlet context with the email service key, which will return our mocked EmailListService (note, in this test we don’t actually implement the service interface, we just mock it like everything else).

The “no list name” exception-checking test is also a bit more complicated than the previous example:

1
2
3
4
5
6
7
8
9
10
11
@Test(expected=IOException.class)
public void doGet_without_list() throws Exception {
    mockery.checking(new Expectations(){
        {
            one(request).getParameter("listName"); will(returnValue(null));
            one(emailListService).getListByName(null); will(throwException(new IOException()));
        }
    });

    servlet.doGet(request, response);
}

We actually need to code the behavior for a null return of the “listName” parameter and cause the exception to be thrown by the service. The other test, the “with list name” test is the more interesting of the two now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
public void doGet_with_list() throws Exception {
    final PrintWriter writer = mockery.mock(PrintWriter.class);
    final Sequence printSequence = mockery.sequence("printSequence");
    mockery.checking(new Expectations(){
        {
            one(request).getParameter("listName"); will(returnValue("foolist"));

            final List<String> list = Arrays.asList("larry@stooge.com","moe@stooge.com","curley@stooge.com");
            one(emailListService).getListByName("foolist"); will(returnValue( list ));

            one(response).getWriter(); will(returnValue(writer));

            one(writer).println("larry@stooge.com"); inSequence(printSequence);
            one(writer).println("moe@stooge.com"); inSequence(printSequence);
            one(writer).println("curley@stooge.com"); inSequence(printSequence);
            one(writer).close(); inSequence(printSequence);
        }
    });

    servlet.doGet(request, response);
}

You will see again, that the basic call behavior is specified as is the service return value, but here, also we actually see some of the benefit of all this extra code. Notice the sequence behavior. You can define a sequence of calls which must be performed in the order specified or the test will fail. This is useful in cases like this where, if nothing else, you want to ensure that the close() method is called after all of the println() calls on the writer.

The whole test case is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@RunWith(JMock.class)
public class EmailListServlet_JMockTest {
    private Mockery mockery = new JUnit4Mockery();
    private EmailListServlet servlet;
    private HttpServletRequest request;
    private HttpServletResponse response;
    private EmailListService emailListService;

    public EmailListServlet_JMockTest(){
        mockery.setImposteriser(ClassImposteriser.INSTANCE);
    }

    @Before
    public void before() throws ServletException {
        this.emailListService = mockery.mock(EmailListService.class);

        final ServletConfig servletConfig = mockery.mock(ServletConfig.class);
        mockery.checking(new Expectations(){
            {
                final ServletContext servletContext = mockery.mock(ServletContext.class);
                one(servletConfig).getServletContext(); will(returnValue(servletContext));
                one(servletContext).getAttribute(EmailListService.KEY); will(returnValue(emailListService));
            }
        });

        this.servlet = new EmailListServlet();
        servlet.init(servletConfig);

        this.request = mockery.mock(HttpServletRequest.class);
        this.response = mockery.mock(HttpServletResponse.class);
    }

    @Test(expected=IOException.class)
    public void doGet_without_list() throws Exception {
        mockery.checking(new Expectations(){
            {
                one(request).getParameter("listName"); will(returnValue(null));
                one(emailListService).getListByName(null); will(throwException(new IOException()));
            }
        });

        servlet.doGet(request, response);
    }

    @Test
    public void doGet_with_list() throws Exception {
        final PrintWriter writer = mockery.mock(PrintWriter.class);
        final Sequence printSequence = mockery.sequence("printSequence");
        mockery.checking(new Expectations(){
            {
                one(request).getParameter("listName"); will(returnValue("foolist"));

                final List<String> list = Arrays.asList("larry@stooge.com","moe@stooge.com","curley@stooge.com");
                one(emailListService).getListByName("foolist"); will(returnValue( list ));
                one(response).getWriter(); will(returnValue(writer));
                one(writer).println("larry@stooge.com"); inSequence(printSequence);
                one(writer).println("moe@stooge.com"); inSequence(printSequence);
                one(writer).println("curley@stooge.com"); inSequence(printSequence);
                one(writer).close(); inSequence(printSequence);
            }
        });

        servlet.doGet(request, response);
    }
}

JMock has a good amount of development time under its belt so it is pretty well documented and tested itself. It’s got a great API for writing your own parameter matchers, method matchers and expectations. It can be a bit cumbersome at times when the test cases get large and full of a lot of mock plumbing. I tend to try and treat test code with the same refactoring attention that I do normal code… pulling out shared expectations, and creating useful shared assertions, etc, then it’s not so bad. There is definitely more code involved with this approach than with something like spring mock; however, you do have quite a wide range of mock-ability that you don’t really get with predefined mock implementations.

You can find the source code used in this posting in my TourDeMock project.

Popularity: 38% [?]

  • Share/Bookmark

Tags: , , , ,

Mocking Objects With Non-Empty Constructors

While writing mock objects with JMock, I have run into a reoccurring issue, you cannot mock concrete classes that do not have an empty constructor (this has been addressed by the JMock development team; however, the specific code line has not yet been released). Sometimes, for one reason or another, you have neither an interface nor empty constructor to mock an object with. The way JMock creates its proxied mock objects is “on creation”, meaning that when you create the mock, the proxy object is created and stored, thereby not allowing you any way to specify constructor arguments.

With a little extension to the mocking API you can still mock those classes. The solution is a simple extension of the CGLIB-based functionality that is already there such that the proxy is created only when the proxy() method is called. The code of the two classes needed is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class CGLIBCoreLazyMock extends AbstractDynamicMock implements MethodInterceptor {

        private Enhancer enhancer;
        private Class[] argTypes;
        private Object[] args;
        private Object proxy;

        public CGLIBCoreLazyMock(Class mockedType,Class[] argTypes,Object[] args){
                super(
                        mockedType,
                        mockNameFromClass(mockedType),
                        new LIFOInvocationDispatcher()
                );
                this.argTypes = argTypes;
                this.args = args;
                this.enhancer = new Enhancer();
                enhancer.setSuperclass(mockedType);
                enhancer.setCallback(this);
        }

        public Object proxy() {
                if(proxy == null){
                        this.proxy = enhancer.create(argTypes,args);
                }
                return(proxy);
        }

        public Object intercept(Object thisProxy, Method method,
                Object[] args, MethodProxy superProxy ) throws Throwable {
                return mockInvocation(new Invocation(proxy,method,args));
        }
}

and then a Mock extension.

1
2
3
4
5
public class LazyMock extends org.jmock.Mock {
        public LazyMock(Class mockedType,Class[] argTypes,Object[] args){
                super(new CGLIBCoreLazyMock(mockedType,argTypes,args));
        }
}

By adding this functionality to JMock, you can mock these classes and still use all of the stub and expectation features that JMock provides. My first resolution to this problem was a quick custom hack using CGLIB. As it threatened to get more complex, I took a peek at the JMock source and found that it would not be hard to implement.

I guess I could have gotten the source and added it directly to their code base, and I even looked at doing that right off, but their project was Ant-based and seemed to be missing some of the pieces required for the build. I just made a little extension jar and it seems to work well enough.

Update: JMock 2 fixes this issue internally and has a lot of other improvements. See Are You Still Mocking Me? for updated information.

Popularity: 4% [?]

  • Share/Bookmark

Tags: , , ,

Are You Still Mocking Me?

JMock 2 came out not too long ago and after some initial worry about backwards compatibility I decided to give it a try. It plays very nicely with version one, but you will want to run out and convert all of your tests once you see how truly beautiful version two is.

A few years ago, I wrote a brief article on unit testing with JMock called “Are You Mocking Me?“. I would like to showcase some of the new goodies in version two by revisiting that article and converting the examples to the newer version. You should at least skim the other article to get a feel for the example at hand as I will be covering mocking differences, not the original issue of mock testing.

In the example, our test was written as an extension of MockObjectTestCase, this is still the case (pardon the pun), except that the package is different, we are now using the org.jmock.integration.junit3.MockObjectTestCase class from version two. It serves basically the same purpose, to provide some helper methods. Our our original test case was:

1
2
3
4
5
6
7
8
9
10
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockPageCtx = new Mock(PageContext.class);

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());
        }
}

which, when updated will become:

1
2
3
4
5
6
7
8
9
10
11
public class HelloTagTest extends MockObjectTestCase {

     public void testHello() throws Exception {
          final PageContext pageCtx = mock(PageContext.class);

          final HelloTag helloTag = new HelloTag();
          helloTag.setPageContext(pageCtx);

          assertEquals("Hello, Mr. Anderson!"),helloTag.buildOutput());
     }
}

The difference is subtle but very interesting. Now instead of a Mock object, we have an instance of the object that was mocked and we no longer need to call the proxy() method and do the casting.

The second example adds a stubbed method, which after using JMock for a while I realized was not such a great thing, since it does not really verify that it was called, just that it can be called.

1
2
3
4
5
6
7
8
9
10
11
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockPageCtx = new Mock(PageContext.class);
                mockPageCtx.stubs().method("findAttribute").with(eq("foo")).will(returnValue("Mr. Anderson"));

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());
        }
}

The new version both takes care of that omission and updates the code to use the new expectation definition method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class HelloTagTest extends MockObjectTestCase {

     public void testHello() throws Exception {
          final PageContext pageCtx = mock(PageContext.class);
          checking(new Expectations(){
               {
                     one(pageCtx).findAttribute("foo"); will(returnValue("Mr. Anderson"));
                }
          });

          final HelloTag helloTag = new HelloTag();
          helloTag.setPageContext(pageCtx);

          assertEquals("Hello, Mr. Anderson!"),helloTag.buildOutput());
     }
}

Now, the first time I saw the code in the checking method, I had to double check that I was looking at a Java example. Basically you are creating an anonymous extension of the Expectations class and then adding an instance initializer to it (the inner curly braces) to provide the expectations themselves. Notice that the method is actually being called on the mocked object; it’s not a string, which means that refactoring will not break your mock tests. If you have never run into that problem with version one, count yourself lucky.

Okay, I am going to jump down to the final code to finish up:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockJspWriter = new Mock(JspWriterMockAdapter.class);
                mockJspWriter.expects(once()).method("print")
                        .with(eq("Hello, Mr. Anderson!"));

                Mock mockPageCtx = new Mock(PageContext.class);
                mockPageCtx.stubs().method("findAttribute").with(eq("matrix"))
                     .will(returnValue("Mr. Anderson"));
                mockPageCtx.stubs().method("getOut").withNoParameters()
                     .will(returnValue((JspWriter)mockJspWriter.proxy()));

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());
                helloTag.setId("matrix");
                helloTag.doStartTag();
                helloTag.doEndTag();

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());

                mockJspWriter.verify();
        }
}

With version two you can mock objects that do not have an empty constructor, though you have to set a non-default “Imposterizer”. This negates the need for the adapter class defined in the old article.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class HelloTagTest extends MockObjectTestCase {

     public HelloTagTest(){
          setImposterizer(ClassImposterizer.INSTANCE);
     }

     public void testHello() throws Exception {
          final JspWriter jspWriter = mock(JspWriter.class);
          checking(new Expectations(){
               {
                     one(jspWriter).print("Hello, Mr. Anderson!");
                }
          });

          final PageContext pageCtx = mock(PageContext.class);
          checking(new Expectations(){
               {
                     one(pageCtx).findAttribute("martix"); will(returnValue("Mr. Anderson"));
                     one(pageCtx).getOut(); will(returnValue(jspWriter));
                }
          });

          final HelloTag helloTag = new HelloTag();
          helloTag.setPageContext(pageCtx);
          helloTag.setId("matrix");
          helloTag.doStartTag();
          helloTag.doEndTag();

          assertEquals("Hello, Mr. Anderson!"),helloTag.buildOutput());
     }
}

You can’t tell me that is not cleaner and more straight-forward. You could actually collapse the checking() methods into one if you wanted to. I tend to group them like the example above since it can often reveal common blocks of code that can be extracted into separate shared methods.

The is a lot more to discuss with JMock but this gives you a good overview based on old version one code.

Popularity: 15% [?]

  • Share/Bookmark

Tags: , , , ,

Are You Mocking Me?

Most of us agree that unit testing is an important part of development and that unit tests should be isolated as much as possible from external configuration and management issues so that you test only the object under examination and not the rest of the environment surrounding them; this is where mocking comes in handy.

Let’s say I want to develop a JSP tag that pulls a name from somewhere in the scope available to the tag and then renders a hello message to the given name. It’s not a very useful tag, but it will work as an example. First, setup the test and a method to test for the desired output.

1
2
3
4
5
6
public class HelloTagTest extends TestCase {
        public void testHello() throws Exception {
                HelloTag helloTag = new HelloTag();
                assertEquals("Hello, Mr. Anderson!", helloTag.buildOutput());
        }
}

I am using test-driven development techniques here, so we want to start simple and build only what we need to accomplish our goal. When you compile this code (I am intentionally leaving out imports to save space) it will fail because we have not yet created a HelloTag class. Let’s do that now.

1
2
3
public class HelloTag extends TagSupport {
        String buildOutput(){}
}

Notice that I also added the buildOutput() method. It is a package-scoped method because it is the method we will be testing for the tag output. This allows the testing of the tag without having to worry about start and end tag support right away. Both classes should now compile, but the test will fail. The quickest way to get the test to work is to fake the return value from buildOutput().

1
2
3
4
5
public class HelloTag extends TagSupport {
        String buildOutput(){
                return( "Hello, Mr. Anderson!" );
        }
}

If you run the test now, everything is green, though not very useful. We want to be able to pull the name of the person from the page context. The page context is passed to the tag by the tag container, so how do we use it “out of the container” This is where mocking comes into play. I use JMock for mocking. It is easy to use once you get the hang of it, and very powerful.

We need to create a mock PageContext so that we don’t need a whole servlet container to test this one little tag. Let’s flesh out the mock context and then add it to the test case.

1
Mock mockPageCtx = new Mock(PageContext.class);

You will need to import the [cglib](http://cglib.sourceforge.net) version of the mock api (org.jmock.cglib.*) due to the fact that PageContext is not an interface. With JMock you can mock interfaces or classes as long as they have an empty constructor.

To use the mock object as the “real” thing, you just create a proxy.

1
PageContext pageCtx = (PageContext)mockPageCtx.proxy();

Let’s add this to our test case.

1
2
3
4
5
6
7
8
9
10
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockPageCtx = new Mock(PageContext.class);

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());

                assertEquals( "Hello, Mr. Anderson!", helloTag.buildOutput());
        }
}

Notice that we are using MockObjectTestCase instead of TestCase.

If you run the test, everything is still fine. We are not using the PageContext yet. We need the page context to be able to provide the name for us when we request it. Let’s say its stored somewhere in scope under the id foo. We need to tell the mockPageCtx to return the correct value when the right conditions are met. This is where the real mocking comes in (and the power of JMock).

1
2
3
4
5
6
7
8
9
10
11
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockPageCtx = new Mock(PageContext.class);
                mockPageCtx.stubs().method("findAttribute").with(eq("foo")).will(returnValue( "Mr. Anderson" ));

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());
        }
}

We added one line of code that probably looks a little confusing… it did to me when I first learned JMock. You can break it down to:

I want to stub out the method findAttribute that takes the parameter foo and will return the value “Mr. Anderson”.

You are mocking the response of the PageContext instance. The test still runs, but now we need to modify the tag itself to actually use the page context.

1
2
3
4
5
6
public class HelloTag extends TagSupport {
        String buildOutput(){
                String name = (String)pageContext.findAttribute("foo");
                return("Hello, " + name + "!");
        }
}

Now run the test and everything is still green. Your tag thinks it has a real PageContext. Now, let’s say that we want to be able to specify the name of the attribute using a tag attribute called id. As you probably know, tag attributes are simply setters in the tag class.

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockPageCtx = new Mock(PageContext.class);
                mockPageCtx.stubs().method("findAttribute").with(eq("foo")).will(returnValue("Mr. Anderson"));

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());
                helloTag.setId("matrix");

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());
        }
}

Then we need to add the setter to the tag and use the id in the output.

1
2
3
4
5
6
7
8
9
10
public class HelloTag extends TagSupport {
        private String id;

        public void setId(String id){this.id = id;}

        String buildOutput(){
                String name = (String)pageContext.findAttribute(id);
                return("Hello, " + name + "!");
        }
}

Aww, but now the test fails. The expected findAttribute() parameter was not found. We need to modify our test to expect the right one.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockPageCtx = new Mock(PageContext.class);
                mockPageCtx.stubs().method("findAttribute").with(eq("matrix"))
                     .will(returnValue("Mr. Anderson"));

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());
                helloTag.setId("matrix");

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());
        }
}

And now everything is green again.

Let’s take a break for a second and look at what we have. We have a completely tested JSP tag (though not fully implemented) that does everything we need it to do. Now we just need to add the rest of the tag support so that it will work in a servlet container. Let’s write out our output in the doEndTag() method. Can we test this to make sure we are outputting the right data? Yes, another job for JMock, with a little help from a concrete mock helper. We need to mock JspWriter, which is abstract and has no empty constructor… no JMock friendly. So, what I do is make a simple mock adapter for it.

1
2
3
4
5
public abstract JspWriterMockAdapter extends JspWriter {
        public JspWriterMockAdapter(){
                super(1024,false);
        }
}

Which we can then use with JMock to test for the expected output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class HelloTagTest extends MockObjectTestCase {
        public void testHello() throws Exception {
                Mock mockJspWriter = new Mock(JspWriterMockAdapter.class);
                mockJspWriter.expects(once()).method("print")
                        .with(eq("Hello, Mr. Anderson!"));

                Mock mockPageCtx = new Mock(PageContext.class);
                mockPageCtx.stubs().method("findAttribute").with(eq("matrix"))
                     .will(returnValue("Mr. Anderson"));
                mockPageCtx.stubs().method("getOut").withNoParameters()
                     .will(returnValue((JspWriter)mockJspWriter.proxy()));

                HelloTag helloTag = new HelloTag();
                helloTag.setPageContext((PageContext)mockPageCtx.proxy());
                helloTag.setId("matrix");
                helloTag.doStartTag();
                helloTag.doEndTag();

                assertEquals("Hello, Mr. Anderson!",helloTag.buildOutput());

                mockJspWriter.verify();
        }
}

This expectation checking shows the other way to use JMock. You can test for an expected method call on the mock object. Here we are saying that the mock JspWriter expects the print() method to be called only once with the given string.

I also added a method stub to return the mock JspWriter when getOut() is called on the PageContext. The last statement in the test method is also important. The verify method is called on the mock object when you want to test for expected method calls. If they are not found, the test fails.

If we run the test now, it will fail because we are not doing anything in the doEndTag() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class HelloTag extends TagSupport {
        private String id;

        public void setId(String id){this.id = id;}

        public int doEndTag() throws JspException {
                try {
                        pageContext.getOut().print(buildOutput());
                } catch(Exception ex){throw new JspException(ex);}
                return(EVAL_PAGE);
        }

        String buildOutput(){
                String name = (String)pageContext.findAttribute(id);
                return("Hello, " + name + "!");
        }
}

Run the test again and everything is green. Now you also see why I use a separate method to build the output. This keeps your tag methods very simple and allows for greater test coverage. This is as far as I am going to go with this example. It is a fully working JSP tag. If you build a tag descriptor for it and use it, you would see the output we are testing for.

Don’t get me wrong, this approach does not necessarily negate the need for in-container testing, but it can lessen that need in most cases. You can use something like Cactus to do your in-container testing once your mock testing is done. Though my servlet container can fire up pretty fast, it’s still slower than the mock approach when you are in a rapid test-driven cycle.

Update: JMock 2 is a radical change from version one. See “Are You Still Mocking Me?” for an updated version of this posting.

Popularity: 6% [?]

  • Share/Bookmark

Tags: , , , ,

Switch to our mobile site