Discussion:
[groovy-user] Mocking with Groovy
Stefan Gojan
2011-06-19 16:49:12 UTC
Permalink
Hi,

is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest

I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)

kind regards,
Stefan Gojan
--
http://en.gravatar.com/vollekannehoschi

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
René Scheibe
2011-06-19 17:20:32 UTC
Permalink
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.

Regards,
René Scheibe

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Stefan Gojan
2011-06-19 17:39:51 UTC
Permalink
Sorry, you are right getTarget isn't a method of HttpServletRequest. I
mixed it up.
Just replace "getTarget" with "getHeader", how does it work when the
method exists?
def request = [getHeader: {return 'application/json'}] as HttpServletRequest

On Sun, Jun 19, 2011 at 7:20 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.
Regards,
René Scheibe
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
René Scheibe
2011-06-19 21:09:28 UTC
Permalink
Post by Stefan Gojan
Sorry, you are right getTarget isn't a method of HttpServletRequest. I
mixed it up.
Just replace "getTarget" with "getHeader", how does it work when the
method exists?
def request = [getHeader: {return 'application/json'}] as HttpServletRequest
Calling request.getHeader('some name') returns 'application/json' as
expected when you stub the HttpServletRequest as above.

If you still struggle with it, just be more specific what is failing
(provide real source code and real error messages).

In case you want to stub other interfaces or classes, always keep in
mind that closures also have parameters which can be typed. If you don't
specify a parameter (as in your example) the implicit 'it' parameter is
assumed.

Regards,
René Scheibe
Post by Stefan Gojan
On Sun, Jun 19, 2011 at 7:20 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.
Regards,
René Scheibe
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Stefan Gojan
2011-06-20 07:10:43 UTC
Permalink
My question is, how can I change the stubbed behaviour of getHeader:
request = [getHeader: {'application/json'}] as HttpServletRequest
assert request.getHeader() == 'application/json'
HttpServletRequest.metaClass.getHeader = {'foo'}
assert request.getHeader() == 'foo'

Assertion failed:
assert request.getHeader() == 'foo'
| | |
| | false
| application/json
$***@8046f4 (toString() threw
java.lang.UnsupportedOperationException)

Regards,
Stefan

On Sun, Jun 19, 2011 at 11:09 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Sorry, you are right getTarget isn't a method of HttpServletRequest. I
mixed it up.
Just replace "getTarget" with "getHeader", how does it work when the
method exists?
def request = [getHeader: {return 'application/json'}] as HttpServletRequest
Calling request.getHeader('some name') returns 'application/json' as
expected when you stub the HttpServletRequest as above.
If you still struggle with it, just be more specific what is failing
(provide real source code and real error messages).
In case you want to stub other interfaces or classes, always keep in
mind that closures also have parameters which can be typed. If you don't
specify a parameter (as in your example) the implicit 'it' parameter is
assumed.
Regards,
René Scheibe
Post by Stefan Gojan
On Sun, Jun 19, 2011 at 7:20 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.
Regards,
René Scheibe
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Guillaume Laforge
2011-06-20 15:46:10 UTC
Permalink
It's not a problem with your getHeader method, it's because you have
to implement toString in your mock too.
(because as the error message shows: the toString method thew an
exception, because it's the default implementation)

On Mon, Jun 20, 2011 at 09:10, Stefan Gojan
       request = [getHeader: {'application/json'}] as HttpServletRequest
       assert request.getHeader() == 'application/json'
       HttpServletRequest.metaClass.getHeader = {'foo'}
      assert request.getHeader() == 'foo'
assert request.getHeader() == 'foo'
        |           |                   |
        |           |                   false
        |           application/json
java.lang.UnsupportedOperationException)
Regards,
Stefan
On Sun, Jun 19, 2011 at 11:09 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Sorry, you are right getTarget isn't a method of HttpServletRequest. I
mixed it up.
Just replace "getTarget" with "getHeader", how does it work when the
method exists?
def request = [getHeader: {return 'application/json'}] as HttpServletRequest
Calling request.getHeader('some name') returns 'application/json' as
expected when you stub the HttpServletRequest as above.
If you still struggle with it, just be more specific what is failing
(provide real source code and real error messages).
In case you want to stub other interfaces or classes, always keep in
mind that closures also have parameters which can be typed. If you don't
specify a parameter (as in your example) the implicit 'it' parameter is
assumed.
Regards,
René Scheibe
Post by Stefan Gojan
On Sun, Jun 19, 2011 at 7:20 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.
Regards,
René Scheibe
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Stefan Gojan
2011-06-20 18:31:35 UTC
Permalink
I changed the code and it doesn't work either:
request = [getHeader: {'application/json'}, toString:
{'string'}] as HttpServletRequest
assert request.getHeader() == 'application/json'
HttpServletRequest.metaClass.getHeader = {'foo'}
assert request.getHeader() == 'foo'

Assertion failed:
assert request.getHeader() == 'foo'
| | |
string | false
application/json

I think it doesn't work, because request is a Proxy no
HttpServletRequest implementation. I looked at 'request' in the
debugger and found out that a property named 'h' holds the map I wrote
in my first code line. So this works but looks ugly:
request = [getHeader: {'application/json'}, toString:
{'string'}] as HttpServletRequest
assert request.getHeader() == 'application/json'
request.h.delegate['getHeader'] = {'foo'}
assert request.getHeader() == 'foo'

Is there a 'groovy' way to achive the same result?

Kind regards,
Stefan

On Mon, Jun 20, 2011 at 5:46 PM, Guillaume Laforge
Post by Guillaume Laforge
It's not a problem with your getHeader method, it's because you have
to implement toString in your mock too.
(because as the error message shows: the toString method thew an
exception, because it's the default implementation)
On Mon, Jun 20, 2011 at 09:10, Stefan Gojan
       request = [getHeader: {'application/json'}] as HttpServletRequest
       assert request.getHeader() == 'application/json'
       HttpServletRequest.metaClass.getHeader = {'foo'}
      assert request.getHeader() == 'foo'
assert request.getHeader() == 'foo'
        |           |                   |
        |           |                   false
        |           application/json
java.lang.UnsupportedOperationException)
Regards,
Stefan
On Sun, Jun 19, 2011 at 11:09 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Sorry, you are right getTarget isn't a method of HttpServletRequest. I
mixed it up.
Just replace "getTarget" with "getHeader", how does it work when the
method exists?
def request = [getHeader: {return 'application/json'}] as HttpServletRequest
Calling request.getHeader('some name') returns 'application/json' as
expected when you stub the HttpServletRequest as above.
If you still struggle with it, just be more specific what is failing
(provide real source code and real error messages).
In case you want to stub other interfaces or classes, always keep in
mind that closures also have parameters which can be typed. If you don't
specify a parameter (as in your example) the implicit 'it' parameter is
assumed.
Regards,
René Scheibe
Post by Stefan Gojan
On Sun, Jun 19, 2011 at 7:20 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.
Regards,
René Scheibe
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Guillaume Laforge
2011-06-21 10:07:20 UTC
Permalink
Right, now I think I know what's going on, after I checked how I
mocked the request myself on the Gaelyk project
(http://gaelyk.appspot.com).
Here's an example:

private request = [
getRequestURI: { -> recorder << "req.getRequestURI"; uri },
getQueryString: { -> recorder << "req.getQueryString"; "" },
getRequestDispatcher: { String s -> recorder <<
"req.getRequestDispatcher"; requestDispatcher },
getHeader: { String h -> recorder << "req.getHeader"; dateAfter }
] as HttpServletRequest

See how I use the arrow?
Methods like getRequestURI() don't take any parameter, or getHeader()
takes a String parameter.
So it's important to have the right signature, ie. the right number of
parameters with their correct types as parameters of your closures.

Guillaume

On Mon, Jun 20, 2011 at 20:31, Stefan Gojan
Post by Stefan Gojan
{'string'}] as HttpServletRequest
       assert request.getHeader() == 'application/json'
       HttpServletRequest.metaClass.getHeader = {'foo'}
       assert request.getHeader() == 'foo'
assert request.getHeader() == 'foo'
      |         |           |
      string  |           false
              application/json
I think it doesn't work, because request is a Proxy no
HttpServletRequest implementation. I looked at 'request' in the
{'string'}] as HttpServletRequest
       assert request.getHeader() == 'application/json'
       request.h.delegate['getHeader'] = {'foo'}
       assert request.getHeader() == 'foo'
Is there a 'groovy' way to achive the same result?
Kind regards,
Stefan
On Mon, Jun 20, 2011 at 5:46 PM, Guillaume Laforge
Post by Guillaume Laforge
It's not a problem with your getHeader method, it's because you have
to implement toString in your mock too.
(because as the error message shows: the toString method thew an
exception, because it's the default implementation)
On Mon, Jun 20, 2011 at 09:10, Stefan Gojan
       request = [getHeader: {'application/json'}] as HttpServletRequest
       assert request.getHeader() == 'application/json'
       HttpServletRequest.metaClass.getHeader = {'foo'}
      assert request.getHeader() == 'foo'
assert request.getHeader() == 'foo'
        |           |                   |
        |           |                   false
        |           application/json
java.lang.UnsupportedOperationException)
Regards,
Stefan
On Sun, Jun 19, 2011 at 11:09 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Sorry, you are right getTarget isn't a method of HttpServletRequest. I
mixed it up.
Just replace "getTarget" with "getHeader", how does it work when the
method exists?
def request = [getHeader: {return 'application/json'}] as HttpServletRequest
Calling request.getHeader('some name') returns 'application/json' as
expected when you stub the HttpServletRequest as above.
If you still struggle with it, just be more specific what is failing
(provide real source code and real error messages).
In case you want to stub other interfaces or classes, always keep in
mind that closures also have parameters which can be typed. If you don't
specify a parameter (as in your example) the implicit 'it' parameter is
assumed.
Regards,
René Scheibe
Post by Stefan Gojan
On Sun, Jun 19, 2011 at 7:20 PM, René Scheibe
Post by René Scheibe
Post by Stefan Gojan
Hi,
is there a way to change a mocked method when I use this code to mock a class?
// my mocked request
def request = [getTarget: {return 'foo/bar'}] as HttpServletRequest
There is no getTarget method in HttpServletRequest. So your code would
not stub it but create a new method. As HttpServletRequest is an
interface and the proxy generated via '...as HttpServletRequest' only
meets this interface your method cannot be called on request.
Post by Stefan Gojan
I tried to assign a new closure to
"HttpServeletRequest.metaClass.getTarget" which don't work :(
I hope someone can help me. I love groovy code much more for testing
like any other test framework out there ;)
Better don't globally change a so widely used interface. This could lead
to strange behavior.
Regards,
René Scheibe
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Peter Niederwieser
2011-06-22 04:04:50 UTC
Permalink
Ironically, you would have saved yourself a headache by using a mocking
framework. For example, in Spock you could do:

def request = Mock(HttpServletRequest)
request.header >>> ['application/json', 'foo']

expect:
request.header == 'application/json'
request.header == 'foo'

Every Spock mock comes free with a sensible toString(), equals(), and
hashCode() implementation.

Cheers,
Peter





--
View this message in context: http://groovy.329449.n5.nabble.com/Mocking-with-Groovy-tp4503856p4512854.html
Sent from the groovy - user mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Stefan Gojan
2011-06-22 08:27:26 UTC
Permalink
Peter is right ... I thought don't need the extra power of a mocking
framework, but it makes life easier.

Thanks for all the answers,
Stefan
Post by Peter Niederwieser
Ironically, you would have saved yourself a headache by using a mocking
def request = Mock(HttpServletRequest)
request.header >>> ['application/json', 'foo']
request.header == 'application/json'
request.header == 'foo'
Every Spock mock comes free with a sensible toString(), equals(), and
hashCode() implementation.
Cheers,
Peter
--
View this message in context: http://groovy.329449.n5.nabble.com/Mocking-with-Groovy-tp4503856p4512854.html
Sent from the groovy - user mailing list archive at Nabble.com.
---------------------------------------------------------------------
   http://xircles.codehaus.org/manage_email
--
http://en.gravatar.com/vollekannehoschi

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Loading...