Spock Issue 305 - Freeing Spock Mocks from Specifications

857 views
Skip to first unread message

Damokles

unread,
Aug 14, 2013, 8:43:28 PM8/14/13
to spockfr...@googlegroups.com
As already requested in https://code.google.com/p/spock/issues/detail?id=305 the idea is to allow the creation of spock mocks outside of a Specification.

Peter:
it shouldn't be too difficult to support this use case.

So I wanted to start a discussion about how this feature should be implemented.

Some of you are probably working with mockito as mocking framework for spring.
There is a really nice helper library Springockito that allows easy creation of mocks and spies in
springcontexts.

So I would suggest that spock supports something similar to declare mocks and spies in spring:
<spock:mock id="..." class="targetClass" />
<spock:spy bean="targetBean" />

So if you wanted to use such a mock you would have to use @Inject/@Autowired to inject it into
your specification. Spock should then attach the mock to the current specification and allow the
definition of the behavior. After each feature run the mock would need to be reset and at the end
of the spec detached.

I really want this feature. since at the moment I have to rely on mockito for spring injected mocks
and seeing both mocking apis side by side really makes it obvious that spock mocks are far
easier and groovier to work with.

Peter Niederwieser

unread,
Aug 24, 2013, 2:52:46 PM8/24/13
to spockfr...@googlegroups.com
Roughly speaking, this will require:

* A standalone API for creating detached mocks
* A way to attach/detach a mock from a specification

I don't plan to work on this myself anytime soon, but if someone comes up with a good solution, I'll definitely consider to pull it.

Cheers,
Peter

Damokles

unread,
Sep 1, 2013, 6:36:37 AM9/1/13
to spockfr...@googlegroups.com
Would you be fine with it if we only supported detached JavaMocks for the first version?
GroovyMocks will require more effort since they do more advanced stuff like manipulating
the metaClass.

Cheers,

Leonard

Damokles

unread,
Sep 1, 2013, 7:55:05 AM9/1/13
to spockfr...@googlegroups.com
I think I got the prototype working. Could you please take a look at https://github.com/leonard84/spock/tree/detached-mocks
and tell me if I'm going in the right direction and what needs to be changed in order for it to be integrated into spock.

Cheers,

Leonard

Damokles

unread,
Sep 1, 2013, 11:36:24 AM9/1/13
to spockfr...@googlegroups.com
Is there a reason why the MockDetector (now MockUtil) has instance methods instead of static methods?
If not I'd like to make them static.

Damokles

unread,
Sep 1, 2013, 1:55:26 PM9/1/13
to spockfr...@googlegroups.com
I managed to  get the Spring integration working.

One thing to figure out is how to inject a configured instance into the Spy instead of letting
the Spy construct the instance by itself. This way we can wrap existing and configured
SpringBeans which can be quite helpful in an integration test context.

Peter Niederwieser

unread,
Sep 12, 2013, 2:04:07 AM9/12/13
to spockfr...@googlegroups.com
Thanks a lot for the pull request. To answer some of your questions:

* Only supporting "Java" mocks/stubs/spies is certainly fine for now.
* MockDetector has instance methods because I considered it a better design (it might become stateful/configurable at some point in the future).
* Giving up on controlling construction of the spied-on instance is problematic. It would essentially mean to introduce another kind of spy that's less powerful (i.e. can't be used for partial mocking) and behaves differently in some situations. I don't want to go there right now, but we can reconsider this decision at a later point.

I hope to have a closer look at your code over the weekend.

Cheers,
Peter

Damokles

unread,
Sep 12, 2013, 5:23:24 PM9/12/13
to spockfr...@googlegroups.com
Why would you need to give up partial mocking? The way I see it, is that you have a normal mock that by default delegates all non mocked calls to the spied instance. Mockito certainly supports this kind of spying.

Cheers,

Leonard

Peter Niederwieser

unread,
Sep 12, 2013, 8:04:09 PM9/12/13
to spockfr...@googlegroups.com
On Sep 12, 2013, at 2:23 PM, Damokles <l.bru...@googlemail.com> wrote:

> Why would you need to give up partial mocking? The way I see it, is that you have a normal mock that by default delegates all non mocked calls to the spied instance. Mockito certainly supports this kind of spying.

As soon as you delegate rather than subclass, partial mocking will no longer be possible, because the spy won't be able to intercept a call from `delegate.foo` to `delegate.bar`. Mockito started out with delegation, and later added a second kind of spy for this and other reasons. If possible, I'd like to avoid supporting two kinds of spies.

Cheers,
Peter

signature.asc

Leonard Brünings

unread,
Sep 13, 2013, 7:20:03 PM9/13/13
to spockfr...@googlegroups.com
The usecase I see for delegation is, if you have an integration test and you want to make sure that a call to an external system was made you can simply wrap the instance in a spy and verify the call. Assuming that the instance doing the call is complex to setup.

But what about the following: You could use the instance as a prototype by copying all fields to the actual spy, since you are using objenesis no constructor is called and the instance is used to set the correct state. This way you don't need to delegate and you can still to partial mocking, but you can also setup the correct internal state. ?

Leonard Brünings

unread,
Sep 19, 2013, 6:53:28 PM9/19/13
to spockfr...@googlegroups.com
Any issues with the code?

Rick Jensen

unread,
Dec 5, 2013, 11:31:41 AM12/5/13
to spockfr...@googlegroups.com
Having the ability to wrap an existing instance with something that can watch for (and count) calls to that instance would be amazing. I'm not particularly familiar with many mocking frameworks, but there's been a number of different times when I wanted that ability.

Turning the spy into the "wrapped" instance by copying everything over to the spy sounds, to me, like it would work.

Marcin Zajączkowski

unread,
Oct 27, 2014, 9:46:46 AM10/27/14
to spockfr...@googlegroups.com
On 2013-09-14 01:20, Leonard Brünings wrote:
> The usecase I see for delegation is, if you have an integration test and
> you want to make sure that a call to an external system was made you can
> simply wrap the instance in a spy and verify the call. Assuming that the
> instance doing the call is complex to setup.

That's one of the main use cases when I use Springockito in my in
integration tests.

> But what about the following: You could use the instance as a prototype by
> copying all fields to the actual spy, since you are using objenesis no
> constructor is called and the instance is used to set the correct state.
> This way you don't need to delegate and you can still to partial mocking,
> but you can also setup the correct internal state. ?

I also wanted to implement an ability to spy existing instances in the
similar way and I found that thread.

@Peter, do you see implementation problems with that approach in Spock?

@Peter, what would be required to modify in detached mocks PR [1] to
make it closer to pull into the code base?

[1] - https://github.com/spockframework/spock/pull/17


Marcin



> On Friday, September 13, 2013 2:04:09 AM UTC+2, Peter Niederwieser wrote:
>>
>> On Sep 12, 2013, at 2:23 PM, Damokles <l.bru...@googlemail.com<javascript:>>
>> wrote:
>>
>>> Why would you need to give up partial mocking? The way I see it, is that
>> you have a normal mock that by default delegates all non mocked calls to
>> the spied instance. Mockito certainly supports this kind of spying.
>>
>> As soon as you delegate rather than subclass, partial mocking will no
>> longer be possible, because the spy won't be able to intercept a call from
>> `delegate.foo` to `delegate.bar`. Mockito started out with delegation, and
>> later added a second kind of spy for this and other reasons. If possible,
>> I'd like to avoid supporting two kinds of spies.
>>
>> Cheers,
>> Peter
>>
>>
>


--
http://blog.solidsoft.info/ - Working code is not enough

Peter Niederwieser

unread,
Dec 15, 2014, 8:19:18 PM12/15/14
to spockfr...@googlegroups.com
> @Peter, do you see implementation problems with that approach in Spock?

It feels like a huge hack. Then again, it seems to do well in Mockito.

> @Peter, what would be required to modify in detached mocks PR [1] to make it closer to pull into the code base? 

I'd like to see a common API for mock creation that contains all factory methods currently found in `spock.lang.MockingApi`. The implementation that comes with `java.lang.Specification` would automatically attach mocks to the current spec instance. Besides there would be a standalone implementation whose mocks would need to be manually attached to a spec instance. The Spring mock factory bean could then be built on top of the latter.

Cheers,
Peter

Leonard Brünings

unread,
Jan 19, 2015, 1:08:17 PM1/19/15
to spockfr...@googlegroups.com
Hi Peter,


> @Peter, what would be required to modify in detached mocks PR [1] to make it closer to pull into the code base? 

I'd like to see a common API for mock creation that contains all factory methods currently found in `spock.lang.MockingApi`. The implementation that comes with `java.lang.Specification` would automatically attach mocks to the current spec instance. Besides there would be a standalone implementation whose mocks would need to be manually attached to a spec instance. The Spring mock factory bean could then be built on top of the latter.
 
I would be willing to change change the PR, but I'm not sure how to implement it. Should I extract the MockingApi as an interface, or should I extend from it and just overwrite createMock of SpeckInternals and delegate all calls to the MockImple/StubImpl?
Maybe you could give some more guidance on what I would need to change so it can be included in 1.0.

As for the manually attaching to the spec, it does work automatically in the spring context due to the SpringMockTestExecutionListener.

Cheers,
Leonard

On Tuesday, December 16, 2014 at 2:19:18 AM UTC+1, Peter Niederwieser wrote:
> @Peter, do you see implementation problems with that approach in Spock?

It feels like a huge hack. Then again, it seems to do well in Mockito.


Reply all
Reply to author
Forward
0 new messages