An immature new thought

3 views
Skip to first unread message

Johnny

unread,
Mar 14, 2009, 10:22:55 PM3/14/09
to gmoc...@googlegroups.com
I found that someone have asked how to mock the following code in the
grails-user mailing list
(http://www.nabble.com/Mock-createCriteria-on-domain-td22519111.html#a22519111):

def data = User.createCriteria().list(
offset:params.start,
max:params.limit,
sort:params.sort,
order:params.dir)
{
and {
eq("client", session.client)
}
}

And in gmock, I can mock like this in version 0.9:

def criteria = mock {
list(offset: ..., order: ..., invoke {
and(invoke {
eq('client', session.client)
})
}).returns(...)
}
mock(User).static.createCriteria().returns(criteria)

But it is not intuitive enough, and chained method calls are common in
groovy, so I have an immature new thought that support chained method
calls like:

mock(User).static.createCriteria().list(offset: ..., order: ..., invoke
{
and(invoke {
eq('client', ...)
})
}).returns(...)

Here when list() is called, a new mock is created. So this piece of code
is completely equal to the original one.

So, do you like it? :)


Johnny Jian

unread,
Mar 17, 2009, 4:13:07 AM3/17/09
to gmock-dev
any thought?

On 3月15日, 上午10时22分, Johnny <johnnyjia...@gmail.com> wrote:
> I found that someone have asked how to mock the following code in the
> grails-user mailing list
> (http://www.nabble.com/Mock-createCriteria-on-domain-td22519111.html#a...

Julien

unread,
Mar 18, 2009, 3:29:48 AM3/18/09
to gmock-dev
Yes this is an interesting idea. I faced something similar when trying
to mock:
"http://www.google.com".toUrl().text

So how would that work?

Johnny

unread,
Mar 18, 2009, 8:19:31 AM3/18/09
to gmoc...@googlegroups.com
While getting the 'text' property from 'mockUrl.toUrl()', because it is
not a property of MethodRecorder, then we can consider that it is a
chained call, so we can create a new mock which will be the result of
'mockUrl.toUrl()'.

It is not difficult to recognize chained calls. The most difficult part
is to find out the class of the result. We can just always returns a
mock of Object for Groovy, but cannot do so for Java. We have to return
a mock object with a correct Class. It seems to be simple, but it is
not, for example:

def mock = mock(SomeClass)
mock.get(match { it.correct }).list()

And SomeClass looks like:

public class SomeClass {
...
public ClassA get(A a) { ... }
public ClassB get(B b) { ... }
...
}

Then we won't know the class of the result until the method is called
inside the play closure. Nevertheless, we can still use some lazy
strategies to make it works.

With this DSL, we cannot mock chained methods whose names are 'keywords'
like 'returns', 'times', 'once' and so on. Another DSL can avoid this
restriction, but with longer calls. For example:

mock.toURL().returnsMock(URL).inputstream.returnsMock(InputStream).text.returns('test')

It can also simplify our implements, but statement is really too long.
Just a suggestion.

在 2009-03-18三的 00:29 -0700,Julien写道:

Johnny Jian

unread,
Mar 18, 2009, 11:02:08 PM3/18/09
to gmock-dev
Another suggestion:

In the original DSL, if users miss typed 'times' with 'time', it will
be considered as a chained method, then we cannot tell whether it is
just miss-typing or a chained call.

So I suggest a DSL with a 'chains()' method like:

mock.methodA(...).chains().methodB(...) // the class of the result of
methodA() will be lazy determined
mock.methodA(...).chains(ClassB).methodB(...) // definitely declare
the result is an instanceof ClassB

Then, which DSL among these three ones do you prefer?

Julien Gagnet

unread,
Mar 19, 2009, 3:20:34 AM3/19/09
to gmoc...@googlegroups.com
Your point about times being miss-typed is really true.

I love the chains() idea. Let's do it just like you say.

We'll see during the implementation what is best to do about this lazy loading suggestion.

2009/3/19 Johnny Jian <Johnny...@gmail.com>
Reply all
Reply to author
Forward
0 new messages