Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock HttpServletRequest in Spock

We have a ServletFilter we want to unit tests with Spock and check calls to HttpServletRequest.

The following code throws java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/servlet/http/Cookie

def "some meaningless test"(){
    given:
    HttpServletRequest  servletRequest = Mock(HttpServletRequest)

    when:
    1+1

    then:
    true
}

The JavaEE 5 API (and thus the Servlet API) is on the classpath. The Spock version is 0.6-groovy-1.8.

How would we do that right? It works with Mockito but we'd loose the Spock mocking awesomeness.

Edit: We know about Grails and Spring built-in mocking capabilities for Servlet stuff, we'd just like to know if there's a way to do it with Spock mocking. Otherwise you'd have a mix of mocking setup techniques...

like image 845
Florian Thiel Avatar asked May 25 '12 09:05

Florian Thiel


2 Answers

Grails automatically configures each integration test with a MockHttpServletRequest, MockHttpServletResponse, and MockHttpSession that you can use in your tests.

In a unit test you need to import and instantiate a new MockHttpServletRequest.

import org.springframework.mock.web.MockHttpServletRequest

def "some meaningless test"(){
    given:
    def servletRequest = new MockHttpServletRequest()

    when:
    1+1

    then:
    true
}
like image 71
Arturo Herrero Avatar answered Sep 22 '22 03:09

Arturo Herrero


Spock uses JDK dynamic proxies for mocking interfaces, and CGLIB for mocking classes. Mockito uses CGLIB for both. This seems to make a difference in some situations where mocked interfaces (like javax.servlet.http.HttpServletRequest) reference classes (like javax.servlet.http.Cookie). Apparently, in Spock's case the Cookie class gets loaded, which results in a class loading error because the classes in the servlet API Jar have no method bodies (rather than empty method bodies).

Currently, Spock doesn't provide a way to force the usage of CGLIB for interfaces. This means you can either put the servlet implementation Jar, rather than the API Jar, on the test class path (which is probably the safer bet anyway), or use Mockito.

like image 40
Peter Niederwieser Avatar answered Sep 25 '22 03:09

Peter Niederwieser