I'm struggling to understand something about Spock interactions in a Groovy unit test.
I have the following types:
public interface Bar {
public String getMessage();
}
public class Foo {
private Bar bar;
public void setBar(Bar bar) {
this.bar = bar;
}
public String getMessage() {
return bar.getMessage();
}
}
and I then wrote the following Groovy/Spock test:
class FooSpec extends Specification {
private Bar bar;
private Foo foo;
def setup() {
bar = Mock(Bar) { getMessage() >> "hello" }
foo = new Foo()
foo.bar = bar
}
def "say hello"() {
expect:
foo.message.equals("hello")
}
def "say goodbye"() {
setup:
bar.getMessage() >> "goodbye"
expect:
foo.message.equals("goodbye")
}
}
The code creates a mock Bar
instance in the setup, initializes Bar.getMessage()
to return hello
, and assigns this to a new Foo
instance.
The first test verifies that foo.getMessage()
is equal to hello
.
The second test tries to modify the bar
mock so that it's getMessage
method returns goodbye
. We then expect that foo.getMessage()
(which delegates to bar.getMessage()
) would then return goodbye
. However the test fails as follows:
FooSpec:say goodbye:26 Condition not satisfied
because foo.message
is still equal to hello
.
I also tried the following:
def "say goodbye"() {
when:
bar.getMessage() >> "goodbye"
then:
foo.message.equals("goodbye")
}
and:
def "say goodbye"() {
when:
no_op()
then:
bar.getMessage() >> "goodbye"
foo.message.equals("goodbye")
}
But both failed with the same hello does not equal goodbye message.
I'm probably still thinking in Mockito mode, and assume that an interaction is the equivalent of a when(...).thenReturn(...)
expression, and that later interactions would override earlier interactions.
Is there a simple way using Spock to declare an interaction in a setup
method, then override that interaction in a test case? Or do I need to remove the setup()
method and basically add a setup:
block to each test case?
setup()
method and change my test methods to initialize their state directly (this is also motivated by the fact that I often use awhere:
block in my test methods, and found to my surprise that thesetup()
method was called after thewhere:
block). I think I can understand your example above, but it's not intuitive (it still looks like setup code in thethen:
block to me). – Philis