bgarrels / spock

Automatically exported from code.google.com/p/spock
0 stars 0 forks source link

Cannot specify interactions in both setup/given and then. #129

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem? If possible, provide source code and
stack trace.

package com.mayabansi.webapp.service.spock

import spock.lang.Specification

class OrderProcessServiceSpec extends Specification {

    def "Mock and give cardinality in setup: ONLY works"() {
        given:
            List<Integer> l = Mock()
            1 * l.get(0) >>  2;

        when:
            int i = l.get(0);

        then:
            i == 2
    }

    def "Mock and give cardinality in then: ONLY works"() {
        given:
            List<Integer> l = Mock()

        when:
            int i = l.get(0);

        then:
            1 * l.get(0) >>  2;
            i == 2
    }

    def "Mock, stub in given and check cardinality in interactions does not work"() {
        given:
            List<Integer> l = Mock()
            l.get(0) >>  2;

        when:
            int i = l.get(0);

        then:
            1 * l.get(_)
            i == 2
    }
}

Stack trace:

Condition not satisfied:

i == 2
| |
| false
null

at com.mayabansi.webapp.service.spock.OrderProcessServiceSpec.Mocking and 
checking interactions does not work(OrderProcessServiceSpec.groovy:56)

Process finished with exit code 255

What version of Spock and Groovy are you using?

<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>0.4-groovy-1.6</version>
<scope>test</scope>

Please provide any additional information below. You can also assign
labels.

Linux Mint
Java > 1.6
Groovy > 1.6 (based on Maven I believe)
Spock > 0.4 (based on Maven I believe)
IntelliJ Idea X IU-96.802

Original issue reported on code.google.com by ravi.has...@gmail.com on 28 Sep 2010 at 12:02

Attachments:

GoogleCodeExporter commented 9 years ago
This is expected because interactions specified in a then-block currently have 
precedence over interactions specified elsewhere. And because the interaction 
in the then-block doesn't specify a return value, the default value for the 
mocked method's return type (null in this case) is returned.

Does this behavior cause you any troubles? In general, you shouldn't (have to) 
specify overlapping interactions (i.e. interactions that match the same calls).

Original comment by pnied...@gmail.com on 28 Sep 2010 at 12:16

GoogleCodeExporter commented 9 years ago
Dear Peter,

Beautiful. I completely agree with your reasoning. If Spock will allow 
overlapping interaction(s) in both setup and then, that may cause confusion and 
redundancy.

I was researching online and came across this: 
http://meetspock.appspot.com/?id=16001

There is a spec: "Mocking and checking interaction works"() on line number 15. 
Looking at it I thought it is possible to have same interaction in given and 
then, kind of like Mockito.

Consider this issue closed. I like your explanation, may be we can specify it 
in the Wiki if it is not already done.

Conversely, I am presenting on Mockito and Spock tomorrow 
http://www.sunjug.org/september-2010. Let me know if you would like information 
on it like the demo project on Git for your documentation purposes etc.

Original comment by ravi.has...@gmail.com on 28 Sep 2010 at 1:40

GoogleCodeExporter commented 9 years ago
>If Spock will allow overlapping interaction(s) in both setup and then, that 
may cause confusion and redundancy.

Technically, Spock does allow this, but one interaction will always "win". If 
the stubbed interaction is found first (see below for search order), it will 
always match (as it has no cardinality), and the other interaction won't ever 
get a chance to match. If the mocked interaction is found first, it will match 
until the expected number of invocations has been reached; the next call will 
cause a TooManyInvocationsError. (By the way, the exception name is stolen from 
Mockito).

Search order for interactions is:
1. then-block
2. setup method
3. spec method (e.g. setup-block)

The main reason why then-blocks come first is to allow you to override 
interactions specified, say, in a setup method. I'm not 100% sure this is the 
right decision, but that's how it works at the moment.

Many people think that Spock's mocking framework works like Mockito because it 
also allows to specify interactions after the fact. But in reality, it works 
more like EasyMock and JMock. That is, the interactions must be known 
beforehand. Spock achieves this by moving interactions in then-blocks before 
the corresponding when-block (at compile time). Compared to Mockito, this has 
advantages (e.g. a single interaction can be used for mocking AND stubbing) and 
drawbacks (if you factor out interactions into a helper method and insist on 
calling the helper method from a then-block, you have to wrap the call with 
"interaction { ... }" to help Spock understand that the helper method contains 
interactions).

>Looking at it I thought it is possible to have same interaction in given and 
then, kind of like Mockito.

Yeah, that example gives a wrong impression (it was written by someone else).

>I like your explanation, may be we can specify it in the Wiki if it is not 
already done.

The documentation is definitely lacking, in particular for the mocking 
framework. We'll work on this for 0.5/0.6.

>Conversely, I am presenting on Mockito and Spock tomorrow 
http://www.sunjug.org/september-2010. Let me know if you would like information 
on it like the demo project on Git for your documentation purposes etc.

Cool! I'd definitely like to see your presentation. By the way, for people who 
don't want to give up on Mockito, there is also the option of using it together 
with Spock, enjoying Spock's other benefits.

Original comment by pnied...@gmail.com on 28 Sep 2010 at 3:30

GoogleCodeExporter commented 9 years ago

Original comment by pnied...@gmail.com on 28 Sep 2010 at 3:31

GoogleCodeExporter commented 9 years ago
I will be blog my presentation and I will send you the link. The code is on 
GitHub. Need to clean it up a little bit, before I show it to you :-)

Also, I tried to use Mockito and Spock in same project. I couldn't. Mockito 
doesn't seem to work beyond JUnit 4.4 and Spock needs Junit 4.7. I am using 
Maven on my project and I am a noob to Maven. So I could be doing something 
wrong. Your thoughts? Any way is there a way I can get in touch with you 
directly? Don't want to spam your issue comment section with irrelevant 
comments!!

Original comment by ravi.has...@gmail.com on 29 Sep 2010 at 2:45

GoogleCodeExporter commented 9 years ago
I think the JUnit version problem can be solved. The best place to discuss such 
things is the Spock forum: http://forum.spockframework.org

Original comment by pnied...@gmail.com on 29 Sep 2010 at 9:27