Tuesday, October 13, 2009

java.lang.NoSuchMethodError: org.mockito.Mockito

In a Mockito test case, I have the line:

when(searchService.processSearch(isA(SearchQuery.class)))
   .thenReturn(new StringBuilder(searchResults));

This was giving me the following error when I ran the test case:

java.lang.NoSuchMethodError: org.mockito.Mockito.when(Ljava/lang/Object;)Lorg/mockito/stubbing/OngoingStubbing;
 at au.gov.australia.agosp.web.portlet.search.SearchControllerTest.setUp(SearchControllerTest.java:42)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:122)
 at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:86)
 at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
 at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
 at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
 at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
 at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
 at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
 at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
 at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

This test works on our continuous build server though. The issue was solved after I read Issue 106 reported on Mockito's google code site. Maven updated the mockito jar from 1.7 to 1.8.0, but left both jars in my local repository. Once I removed the 1.7 jar, the test case worked.

Friday, October 02, 2009

JUnit breakpoints skipping in Eclipse debug mode

Sometimes when running a JUnit test case in Eclipse, my breakpoints are all being skipped. Most annoying.

I am using Eclipse Galileo 3.5.0 with JDK 1.6.0_14.

Workaround is to use the following VM argument: -XX:+UseParallelGC. The fix is to upgrade to a later JDK, currently JDK 1.6.0_14. Both methods fixed this issue for me.

Here is the Eclipse bug report for this error and the Stack Overflow report on this issue.

Thursday, October 01, 2009

Url Rewrite Filter duplicates query string parameters

Sun's Webspace portal uses tuckey.org's Url Rewrite Filter, in which you place a bunch of URL rewrite rules in urlrewrite.xml. This is a great way to implement friendly URLs. For example, you can have an easy to type URL that the public will use such as http://www.example.com/search which the Url Rewrite Filter will route to the real portlet/servlet: http://www.example.com/real/path/to/search.

I was debugging a search service when I noticed that the request parameters values were being duplicated by the time it hit my controller. I.e. I was expecting single value parameters in my request:

querywinter sport
advancedSearchfalse

But found this instead (multi valued parameters):

querywinter sportwinter sport
advancedSearchfalsefalse

It turns out that the Url Rewrite Filter was was configured to propagate query parameters when it didn't need to. I.e. I had the following rule in place:

<rule>
   <from>^/search(.*)$</from>
   <to type="forward">/real/path/to/search$1</to>
</rule>

The $1 at the end of the TO element means: put the query parameters (the (.*) grouping in the FORM element) back on the end of the URL. This isn't needed because the Url Rewrite Filter is invoked after the query string has already been processed: the query string parameters have already been parsed and put in the Request object. Thus, the Url Rewrite Filter caused the parameters to be processed a second time.

The fix was simple, once I understood the reason. Just drop $1 from the end of the TO element.

<rule>
   <from>^/search(.*)$</from>
   <to type="forward">/real/path/to/search</to>
</rule>