does MockFor.demand have reserved words like "find" for method names?

70 views
Skip to first unread message

tcox5698

unread,
Mar 8, 2012, 10:42:56 PM3/8/12
to groo...@googlegroups.com
Hi all:

I'm trying to mock out a "find" method on a service - looks like this:

def objectServiceController = new MockFor(ObjectService)
objectServiceController.demand.find {
    "bob"
}

But that doesn't work.  The test passes as though I hadn't recorded the call at all.

If I change "find" to anything else, ie:

def objectServiceController = new MockFor(ObjectService) 
 
objectServiceController.demand.findIt
 "bob" 

Then the test fails as expected.  Is it that I'm just not allowed to mock out methods called "find"?

Thanks for any help.

- Tom C

Colin Harrington

unread,
Mar 9, 2012, 12:22:01 AM3/9/12
to groo...@googlegroups.com
What version of Grails? 
Is this in a unit or integration test?


1st distinction:
Capital-M MockFor()
vs 
Grails' mockFor()

MockFor is part of Groovy.
This would be used like this:
import groovy.mock.interceptor.MockFor
 
def mocker = new MockFor(Collaborator.class// create the Mock support
mocker.demand.one(1..2) { 1 }                 // demand the 'one' method one or two times, returning 1
mocker.demand.two()     { 2 }                 // demand the 'two' method exactly once, returning 2
mocker.use {                                  // start using the Mock
    def caller = new Caller()                 // caller will call Collaborator
    assertEquals 1, caller.collaborateOne()   // will call Collaborator.one
    assertEquals 1, caller.collaborateOne()   // will call Collaborator.one
    assertEquals 2, caller.collaborateTwo()   // will call Collaborator.two
}                                             // implicit verify for strict expectation here

mockFor() is a method on GrailsUnitTestCase
protected GrailsMock mockFor(Class clazz, boolean loose = false)
and would be used like this.
void testSearch() {
      def control = mockFor(SearchService)
      control.demand.searchWeb { String q -> ['mock results'] }
      control.demand.static.logResults { List results ->  }
      controller.searchService = control.createMock()
      controller.search()

assert controller.response.text.contains "Found 1 results" }

mockFor() returns a 'GrailsMock' class - this isn't your mock object.  Its a handle to setup and verify your demands.  This is how you use it:
  1. you setup your demands on this mock handle 
  2. then you create the actual mock (the service) 
  3. Exercise the code which is supposed to utilize the mocked object
  4. verify that the demands were met (control.verify())
Hope this helps,

Colin Harrington
colin.ha...@gmail.com


--
You received this message because you are subscribed to the "Groovy Users of Minnesota" group.
 
To post to this group, send email to groo...@googlegroups.com
To unsubscribe from this group, send email to groovymn-u...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/groovymn?hl=en

tcox5698

unread,
Mar 10, 2012, 1:19:54 PM3/10/12
to Groovy Users of Minnesota
Thanks for your response Colin!

I'm using Grails 2.0.1
I'm writing a unit test.

I'm using capital-M MockFor - the code snippet I provided is a direct
copy paste.

I understand the usage and recognize the snippet you provided from the
Groovy documentation on MockFor.

And - everything works as expected *as long as my method being mocked
is not named "find".*

That is, if the method name is "findIt()", then:
1. the test fails when my method under test does not call the mocked
method as expected. Yay!
2. the test passes when my method under test makes the call as
expected. Yay!

However, if the method being mocked is called "find()", then number 1.
above does not happen, rather I get a false test pass. Not good.

Thanks again for looking.

- Tom C.

On Mar 8, 11:22 pm, Colin Harrington <colin.harring...@gmail.com>
wrote:
> What version of Grails?
> Is this in a unit or integration test?
>
> 1st distinction:
>
> Capital-M MockFor()
>
> vs
>
> Grails' mockFor()
>
> *MockFor* is part of Groovy.http://docs.codehaus.org/display/GROOVY/Using+MockFor+and+StubForhttp://groovy.codehaus.org/gapi/groovy/mock/interceptor/MockFor.html
> This would be used like this:
>
>
>
>
>
>
>
>
>
> > import groovy.mock.interceptor.MockFor
>
> > def mocker = new MockFor(Collaborator.class)  // create the Mock support
> > mocker.demand.one(1..2) { 1 }                 // demand the 'one' method
> > one or two times, returning 1
> > mocker.demand.two()     { 2 }                 // demand the 'two' method
> > exactly once, returning 2
> > mocker.use {                                  // start using the Mock
> >     def caller = new Caller()                 // caller will call
> > Collaborator
> >     assertEquals 1, caller.collaborateOne()   // will call
> > Collaborator.one
> >     assertEquals 1, caller.collaborateOne()   // will call
> > Collaborator.one
> >     assertEquals 2, caller.collaborateTwo()   // will call
> > Collaborator.two
> > }                                             // implicit verify for
> > strict expectation here
>
> *mockFor*() is a method on GrailsUnitTestCase
>
> protected GrailsMock *mockFor*(Class clazz, boolean loose = false)
>
> and would be used like this.
>
> void testSearch() {
>       def control = mockFor(SearchService)
>       control.demand.searchWeb { String q -> ['mock results'] }
>       control.demand.static.logResults { List results ->  }
>       controller.searchService = control.createMock()
>       controller.search()
>
>       assert controller.response.text.contains "Found 1 results"
>
> }
>
> mockFor() returns a 'GrailsMock' class - this isn't your mock object.  Its
> a handle to setup and verify your demands.  This is how you use it:
>
>    1. you setup your demands on this mock handle
>    2. then you create the actual mock (the service)
>    3. Exercise the code which is supposed to utilize the mocked object
>    4. verify that the demands were met (control.verify())
>
> Hope this helps,
>
> Colin Harrington
> colin.harring...@gmail.com
>
>
>
>
>
>
>
> On Thu, Mar 8, 2012 at 9:42 PM, tcox5698 <tcox5...@gmail.com> wrote:
> > Hi all:
>
> > I'm trying to mock out a "find" method on a service - looks like this:
>
> > def objectServiceController = new MockFor(ObjectService)
> >  objectServiceController.demand.find {
> >     "bob"
> > }
>
> > But that doesn't work.  The test passes as though I hadn't recorded the
> > call at all.
>
> > If I change "find" to anything else, ie:
>
> > def objectServiceController = new MockFor(ObjectService)
>
> > objectServiceController.demand.*findIt* {

Matt

unread,
Mar 10, 2012, 7:20:33 PM3/10/12
to Groovy Users of Minnesota
Hi Tom,

groovy.mock.interceptor.Demand uses invokeMethod to handle these
calls, but it will only intercept missing methods. So most of these
methods won't work: http://groovy.codehaus.org/groovy-jdk/java/lang/Object.html

You could do this:

objectServiceController.demand.invokeMethod('find', [{ -> 'bob' }])

or this:

objectServiceController.demand.recorded << new CallSpec(name:'find',
behavior:{ -> 'bob'}, range: 1..1)

- Matt
> > *MockFor* is part of Groovy.http://docs.codehaus.org/display/GROOVY/Using+MockFor+and+StubForhttp...

Matt

unread,
Mar 11, 2012, 4:19:05 PM3/11/12
to Groovy Users of Minnesota
Actually just adding the range will make sure it doesn't match the
existing method.

objectServiceController.demand.find(1) { 'bob' }

tcox5698

unread,
Mar 12, 2012, 5:54:29 PM3/12/12
to Groovy Users of Minnesota
I like that much better - I'll add the range and try it out. Thanks
Matt!
Reply all
Reply to author
Forward
0 new messages