How can I efficiently mock a fluent interface with Spock mocks?
Asked Answered
D

1

16

I'd like to mock some fluent interface with mock, which is basically a mail builder:

this.builder()
            .from(from)
            .to(to)
            .cc(cc)
            .bcc(bcc)
            .template(templateId, templateParameter)
            .send();

When mocking this with Spock, this needs a lot of setup like this:

def builder = Mock(Builder)
builder.from(_) >> builder
builder.to(_) >> builder 

etc. It becomes even more cumbersome when you want to test certain interactions with the mock, depending on the use case. So I basically got two questions here:

  1. Is there a way to combine mock rules, so that I could do a general one time setup of the fluent interface in a method that I can reuse on every test case and then specify additional rules per test-case?
  2. Is there a way to specify the mocking of a fluent interface with less code, e.g. something like:

    def builder = Mock(Builder) builder./(from|to|cc|bcc|template)/(*) >> builder

    or something equivalent to Mockito's Deep Stubs (see http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#RETURNS_DEEP_STUBS)

Durnan answered 27/5, 2013 at 11:50 Comment(0)
A
19

You can do something like this:

def "stubbing and mocking a builder"() {
    def builder = Mock(Builder)
    // could also put this into a setup method
    builder./from|to|cc|bcc|template|send/(*_) >> builder

    when:
    // exercise code that uses builder

    then:
    // interactions in then-block override any other interactions
    // note that you have to repeat the stubbing
    1 * builder.to("fred") >> builder
}
Artemis answered 28/5, 2013 at 10:17 Comment(3)
Great this is working :) Thanks! Any plans to improve this so you don't have to repeat the stubbing in the then -part?Benedetto
We don't have any plans for that. The fact that stubbing and mocking of an interaction occurs together is inherent to how Spock's mocking framework works. It's the same approach as used by JMock, EasyMock, etc. Only Mockito uses a different approach, which has other drawbacks.Artemis
Hi @PeterNiederwieser, can you explain why we need to repeat the stubbing in the then-block?Lenlena

© 2022 - 2024 — McMap. All rights reserved.