Reputation: 9
I'm trying to verify some methods are called for a newly created instance.
I followed Spock guide of mock constructor but it says too few invocations.
Too few invocations for:
3 * mockStep.addTarget(_) (0 invocations)
Unmatched invocations (ordered by similarity):
None
Pasting my code here...
public class Workflow {
public void createStep() {
Step step = new Step();
step.addTarget("A");
step.addTarget("B");
step.addTarget("C");
}
}
class WorkflowTest extends Specification {
Workflow workflow
def setup() {
workflow = new Workflow()
}
def "each new step should have 3 targets" () {
given:
def mockStep = Mock(Step)
GroovySpy(Step, global: true)
new Step() >> mockStep
when:
workflow.createStep()
then:
3 * mockStep.addTarget(_)
}
}
In the above code I'm trying to let all new Step() returns the mocked Step and to verify the mockStep.addTarget() is called 3 times. When I ran in debug mode, it seems Step step = new Step();
still returns a new instance instead of the mocked Step.
Upvotes: 0
Views: 1282
Reputation: 41
This is a beta feature and no grantee it will work as expected and it will be depending on the version you are using .
Please refer to official documentation
Upvotes: 0
Reputation: 67317
Don't use dirty tricks like global Groovy mocks but refactor for decoupling, dependency injection and the resulting better testability instead. Please read the "general comments" and "some more remarks" sections of my answer here for a reason why you should refactor. I do not want to repeat everything here.
As for the technical reason why your global Groovy mock does not work from Java code, I am quoting the Spock manaual:
When should Groovy mocks be favored over regular mocks?
Groovy mocks should be used when the code under specification is written in Groovy and some of the unique Groovy mock features are needed. When called from Java code, Groovy mocks will behave like regular mocks. Note that it isn’t necessary to use a Groovy mock merely because the code under specification and/or mocked type is written in Groovy. Unless you have a concrete reason to use a Groovy mock, prefer a regular mock.
Update:
The quickest way to refactor is to separate creating the step from adding targets. Actually the name createStep
implies the method does just that. But instead it also adds targets. Use two methods for that and a method doing the workflow. Then you can use a Spy
for stubbing createStep
(which returns the created Step
instance) and then check interactions if you really think that should be tested at all. Checking internal interactions is often a code smell (over-specification).
Alternatively, add a factory class for steps and inject an instance into the workflow class. Then you can easily mock the factory class and make it return a mock step.
If you don't understand what I mean by the two alternatives, please let me know.
Upvotes: 1