spockframework / spock

The Enterprise-ready testing and specification framework.
https://spockframework.org
Apache License 2.0
3.55k stars 470 forks source link

groovy mocks are not truthy #438

Open robfletcher opened 9 years ago

robfletcher commented 9 years ago

Originally reported on Google Code with ID 316

See the example below.
Regular mocks evaluate to true but groovy mocks resolve to false.

class GroovyMockSpec extends Specification {
    def mock = Mock(A)
    def groovyMock = GroovyMock(Object)

    def "regular mocks are truthy"() {
        expect:
        mock ?: 'irrelevant' == mock
    }

    def "groovy mocks are falsey"() {
        expect:
        groovyMock ?: 'unexpected' == 'unexpected'
    }

    static interface A {}
}

What version of Spock and Groovy are you using?
0.7-groovy-1.8

Reported by sgo@thinkerit.be on 2013-06-17 12:36:31

robfletcher commented 9 years ago
Same here: groovy: 2.2.2, spock: 0.7-groovy-2.0

I need it to be working in the same way, as I'm mocking collaborators and with GroovyMock
they evaluate to false, and throw exceptions. For now I'll use regular mocks.

Reported by janusz.slota on 2014-04-28 17:22:35

robfletcher commented 9 years ago
Example test http://meetspock.appspot.com/script/5700735861784576

Reported by janusz.slota on 2014-04-28 17:28:47

robfletcher commented 9 years ago
Why is your test depending on the truthiness of a mock object? What's the use case?

Reported by pniederw on 2014-04-28 17:31:12

robfletcher commented 9 years ago
This will do the trick:

def groovyMock = GroovyMock(Map) { asBoolean() >> true }

Perhaps this should be the default. Not sure.

Reported by pniederw on 2014-04-28 17:33:29

robfletcher commented 9 years ago
void initialize() {
    if( ! config) {
        throw new RuntimeException('configuration has not been injected')
    }
    // ... initialize logic
}

I'm not saying it's good design to have initialize method, but it'll work for now.
However GroovyMock config object injected via constructor evaluates to false. Using
Mock, it's OK.

Reported by janusz.slota on 2014-04-28 17:35:22

robfletcher commented 9 years ago
I see. Thanks for the explanation.

By the way, GroovyMock() should only be used where Mock() isn't good enough.

Reported by pniederw on 2014-04-28 17:37:27

robfletcher commented 9 years ago
>> def groovyMock = GroovyMock(Map) { asBoolean() >> true }

Great - thanks for reply. Works perfectly :-)

Reported by janusz.slota on 2014-04-28 17:39:11

robfletcher commented 9 years ago
I see I used the elvis operator so that's probably the specific case I ran into at the
time. I suspect I was doing some kind of lookup and found a GroovyMock instance but
instead I got the value on the right side of the operator.
I don't like having to explicitly define this kind of behavior or the explicit Object
type on the groovy mock or be forced to use null checking instead of the elvis operator.

As for preferring GroovyMock instead of Mock. I understand why you may feel that way
but I do prefer the dynamic aspect of GroovyMock in some cases. Much like how Brian
Marick uses dynamic mocks in his Robozzle kata. (http://vimeo.com/19404746)

Does it not make more sense for Mock and GroovyMock to behave the same way?

Reported by sgo@thinkerit.be on 2014-04-28 18:28:07