How to count closure calls - groovy

How can I count closure method calls.
I have a closure as below:
class SomeTestSpec extends Specification {
def greeting = { "Hello world!" }
#Unroll
def "test description"() {
given: // ….
when:
def v = greeting then: // need something like that: 1 * greeting
}
}
I call it once in the when: clause.
How can I test the call count (one in my case) in the then: clause.

Related

Behaviour test using parametrised Spock framework

I have a set of behavior tests which should result in the same outcome
def 'behaviour tests for route A'() {
when:
doA();
then:
data == 'Hi'
}
def 'behaviour tests for route B'() {
when:
doB();
then:
data == 'Hi'
}
void doA(){
...
}
void doB(){
...
}
the code looks ugly I would have preferred to use parametrized testing. something alongside this:
#Unroll
def 'behaviour tests for route #name'() {
when:
route
then:
data == 'Hi'
where:
name | route
'A' | doA()
'B' | doB()
}
Is there a way to do it?
You can use closures to extract the code that you want executed in the when block.
class ClosureSpec extends Specification {
#Unroll
def 'behaviour tests for route #name'() {
when:
def data = route()
then:
data == 'Hi'
where:
name | route
'A' | { doA() }
'B' | { doB() }
}
def doA() {
return 'Hi'
}
def doB() {
return 'Hi'
}
}
or you could use groovys dynamic nature to pass in the method name
class DynamicSpec extends Specification {
#Unroll
def 'behaviour tests for route #name'() {
when:
def data = this."do$name"()
then:
data == 'Hi'
where:
name | route
'A' | _
'B' | _
}
def doA() {
return 'Hi'
}
def doB() {
return 'Hi'
}
}
Depending on the use-case I'd go with the closure, but the dynamic method name has its uses, especially if you want to pass in parameters.

How to inject Groovy closure variable into Spock mock predicate argument?

I found an interesting line in Spock interactions documentation:
http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_argument_constraints
last line of constraints, example with closure predicate:
1 * subscriber.receive({ it.size() > 3 && it.contains('a') })
My question is: is there a way in Groovy to pass this predicate as variable?
My testing environment code:
class Something {
Doer doer
Something(Doer doer) {
this.doer = doer
}
boolean doSth(x) {
if (!doer.validate(x)) throw new RuntimeException()
true
}
}
class Doer {
boolean validate(int x) {
x == 2
}
}
and test code:
def "some test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
when:
s.doSth(2)
then:
1 * d.validate({ it == 2 }) >> true
}
what I would like to achieve:
def "some test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
def myClosureVar = { ??? }
when:
s.doSth(2)
then:
1 * d.validate(myClosureVar) >> true
}
The closure takes an argument, as indicated by it having a defined value. That value is the corresponding method parameter. So whatever closure you define outside of your interaction, you need to make sure that the interaction hands over that parameter to the closure, i.e. you need to create your own (small and simple) closure evaluating the outer (potentially lengthier, more complex) closure with the parameter it:
1 * d.validate({ myClosureVar(it) }) >> true
Sorry for the repetition, but I always prefer a full MCVE in my answers so you can easily copy, paste, compile and run:
Application classes:
package de.scrum_master.stackoverflow.q60341734
class Doer {
boolean validate(int x) {
x == 2
}
}
package de.scrum_master.stackoverflow.q60341734
class Something {
Doer doer
Something(Doer doer) {
this.doer = doer
}
boolean doSth(x) {
if (!doer.validate(x)) throw new RuntimeException()
true
}
}
Spock specification:
package de.scrum_master.stackoverflow.q60341734
import org.junit.Rule
import org.junit.rules.TestName
import spock.lang.Specification
class SomethingTest extends Specification {
#Rule
TestName testName
def "some test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
when:
s.doSth(2)
then:
1 * d.validate({ println "$testName.methodName: closure parameter = $it"; it == 2 }) >> true
}
def "another test"() {
given:
def d = Mock(Doer)
def s = new Something(d)
def myClosureVar = { println "$testName.methodName: closure parameter = $it"; it == 2 }
when:
s.doSth(2)
then:
1 * d.validate({ myClosureVar(it) }) >> true
}
}
Console log:
some test: closure parameter = 2
another test: closure parameter = 2

How to use IgnoreIf in Spock, when I check the variable?

I need to skip some functions in the program, but it should depend on a variable defined in the same program. How can I do it?
def skip = true
#IgnoreIf({ skip })
def "some function" () {
..
}
Another way to do this is by using spock's configuration file to include/exclude tests or base classes.
First you create your own annotations and place on your tests.
You then write a Spock configuration file.
When you run your tests you can set the spock.configuration property to the configuration file of your choice.
This way you can include/exclude the tests and base classes you want.
Example of spock configuration file:
runner {
println "Run only tests"
exclude envA
}
Your test:
#envA
def "some function" () {
..
}
You can then run :
./gradlew test -Pspock.configuration=mySpockConfig.groovy
Here is a github example
You can do it by accessing skip field in a static context:
import spock.lang.IgnoreIf
import spock.lang.Specification
class IgnoreIfSpec extends Specification {
static boolean skip = true
#IgnoreIf({ IgnoreIfSpec.skip })
def "should not execute this test if `IgnoreIfSepc.skip` is set to TRUE"() {
when:
def res = 1 + 1
then:
res == 2
}
def "should execute this test every time"() {
when:
def res = 1 + 1
then:
res == 2
}
}
Otherwise closure passed to #IgnoreIf() tries to find skip field inside the closure and it fails.
If the variable needs to be computed first and then the decision for test ignoring needs to be taken on the basis of computation, we can use static block and static variable
import spock.lang.IgnoreIf
import spock.lang.Specification
class IgnoreIfSpec extends Specification {
static final boolean skip
static {
//some code for computation
if("some condition")
skip = true
else
skip = false
}
#IgnoreIf({ IgnoreIfSpec.skip })
def "should not execute this test if `IgnoreIfSepc.skip` is set to TRUE"() {
when:
def res = 1 + 1
then:
res == 2
}
def "should execute this test every time"() {
when:
def res = 1 + 1
then:
res == 2
}
}
Another way is:
def skip = true
#IgnoreIf({ instance.skip })
def "some function" () {
..
}
Documentation
instance
The specification instance, if instance fields, shared
fields, or instance methods are needed. If this property is used, the
whole annotated element cannot be skipped up-front without executing
fixtures, data providers and similar. Instead, the whole workflow is
followed up to the feature method invocation, where then the closure
is checked, and it is decided whether to abort the specific iteration
or not.
Then you could do something like:
abstract class BaseTest extends Specification {
boolean skip = false
#IgnoreIf({ instance.skip })
def "some function" () { .. }
}
SubSpecification:
class GoodTest extends BaseTest {
}
class SkipTest extends BaseTest {
boolean skip = true
}
In this case, skip is a property, but it can be a method.

Getting an error with Groovy StubFor when I try and set property value

I have a dynamic AORule class that has a embedded DyanmicRule class instance as a delegate like this, and method on AORule that invokes an action on rule which tests to see if a dynamicExecution closure has been set before calling it:
#Component
#Scope("prototype")
#ActiveObject
#Slf4j
#EqualsAndHashCode
class AORule implements org.easyrules.api.Rule {
//setup delegate dynamicRule and make it a part of this ActiveObject
#Delegate DynamicRule rule
AORule (name, description=null) {
rule = new DynamicRule (name, description ?: "Basic Active Object Rule")
}
AORule () {
rule = new DynamicRule ()
}
....rest of class with a method like this
#ActiveMethod
void active_execute () {
//rule.execute()
if (rule.dynamicExecution != null) {
log.debug "activeExec : running dynamicExecution closure "
rule.dynamicExecute() //should call closure, where this is defined
}
else {
log.debug "activeExec : running std Execution action "
rule.execute()
}
} ....
where the top of the DynamicRule class looks like this:
#InheritConstructors
#Component
#Slf4j //use Groovy AST to get logger
#EqualsAndHashCode
class DynamicRule extends BasicRule implements org.easyrules.api.Rule {
Closure dynamicEvaluation = null
Closure dynamicExecution = null
....
I then try and define a simple Spock test for this and Stub the DynamicRule like so
def "set execution closure directly when doing an execute action " () {
given:"setup of stub for testing "
def mockres
def stub = new StubFor (DynamicRule)
stub.demand.dynamicExecute { mockres = "did nothing" }
stub.demand.getDynamicExecution = {true} // pretend this has been set
when : "execution passing closure value at same time "
//have to run new, actions etc in scope of class stub
stub.use {
def rule = new AORule ()
rule.execute()
}
then : "test execute closure ran as expected "
mockres == "did nothing"
}
In this test - tried to set up the Stub demand for getDynamicExecution property (a closure) to return true, and another demand to stub the method dynamicExecution to set the def mockres result. I then assert that's some value
However this gives me an error like this:
groovy.lang.MissingPropertyException: No such property: getDynamicExecution for class: groovy.mock.interceptor.Demand
at org.easyrules.spring.AORuleSpecTest.set execution closure directly when doing an execute action (AORuleSpecTest.groovy:91)
How do I set the expected result of a mocked property access in a class. I thought setting the the Stub demand expectation for getPropertyName = {some value} would do the trick. What am I doing wrong?
Post Script
I tried to setup a dumbed down version of testing approach I have used like this
class DummyStubSpecTest extends Specification {
def "test z stub " () {
def res
given :
def zstub = new StubFor (Zthing.class)
zstub.demand.execute {res = "hello"}
zstub.demand.getVar {false}
when :
zstub.use {
def a = new Athing()
a.z.execute()
}
then :
res == "hello"
}
def "test Athing stub " () {
def res
given :
def astub = new StubFor (Athing.class)
astub.demand.doit {res = "hello"}
when :
astub.use {
def a = new Athing ()
a.doit()
}
then :
res == "hello"
}
}
and a Spock test like this:
def "test z stub " () {
def res
given :
def zstub = new StubFor (Zthing.class)
zstub.demand.execute {res = "hello"}
zstub.demand.getVar {false}
when :
zstub.use {
def a = new Athing()
a.z.execute()
}
then :
res == "hello"
}
and this does work - so I'm not sure what I am doing wrong in previous example.
Second postscript
One suggestion was that I should use GroovyMock to run the test with, so I tried this
def "set execution closure using GroovyMock to Stub to execute action " () {
given:"setup of stub for testing "
def mockres
GroovyMock (DynamicRule, global:true)
DynamicRule.dynamicExecute() >> {mockres = "did nothing"}
when : "execution passing closure value at same time "
//have to run new, actions etc in scope of class stub
def rule = new AORule ()
rule.execute()
then : "test execute closure ran as expected "
mockres == "did nothing"
}
However when I run this the assertion fails again - mockres is not being set, when the execute() triggers the internal DynamicRule.dynamicExecute() method on my mocked object.
Third Postcript
I have tried again - first a 'dummy pair of classes and dummy test to try groovyMocks - and this works. Here are my eponymous Athing and Zthing
//define subject under test
class Athing {
def z = new Zthing()
def res
def doit() {
z.greet()
res = z.execute()
}
}
//dependency to be stubbed
class Zthing {
def var = true
def execute() {if (var) println "its true" else println "its false"; var}
def greet() { println "hello"}
}
here is the test i defined
class DummyStubSpecTest extends Specification {
def "test z with GroovyMock " () {
given:
def a = new Athing()
def res
def mock = GroovyMock (Zthing) { //, global:true
1*execute() >> {println "stub called"; res=true}
}
a.z = mock
when:
a.doit()
then:
res == true
}
I created the mock and set the interaction expectation (1*) and stubbed response, which sets my external res to some string so I can test for that.
Because the instance of 'a' has an embedded 'z' instance, I overwrite the a.z reference to point to the mock. I then call the SUT in the when clause, and check that res has been set. This does work.
However my real class/test still refuse to work. So my AORule has a DynamicRule reference
class AORule implements org.easyrules.api.Rule {
//setup delegate dynamicRule and make it a part of this ActiveObject
#Delegate DynamicRule rule
AORule (name, description=null) {
rule = new DynamicRule (name, description ?: "Basic Active Object Rule")
}
AORule () {
rule = new DynamicRule ()
} ....
where the execute method in AORule look like this
void execute () {
active_execute()
}
/**
* Active method manages async action through object inside through hidden actor.
* variable 'rule' is the variable we are protecting. Runs either any dynmicExecution closure
* where defined or just runs the standard class execute method
*
* #return void
*/
#ActiveMethod
void active_execute () {
//rule.execute()
if (rule.dynamicExecution != null) {
log.debug "activeExec : running dynamicExecution closure "
rule.dynamicExecute() //should call closure, where this is defined
}
else {
log.debug "activeExec : running std Execution action "
rule.execute()
}
} ....
My test for this looks like this:
def "set execution closure using GroovyMock to Stub out dynamicExecute action " () {
given:"setup of stub for testing "
def mockres
def mock = GroovyMock (DynamicRule) { //, global:true
1*dynamicExecute() >> {-> println "stub called"; mockres = "did nothing" }
0*execute()
}
aorule.rule = mock
when : "execution passing closure value at same time "
//have to run new, actions etc in scope of class stub
//def rule = new AORule ()
aorule.setDynamicExecution {println "hi"}
aorule.execute()
then : "test execute closure ran as expected "
mockres == "did nothing"
}
The test doesn't work correctly - the assertion shows mockres to be null (not being set).
I thought it might be because the activeEvaluate is internally checking on activeEvaluation closure is set, so I tried changing the GroovyMock to a GroovySpy (so that my aorule.setDynamicExecution call should work), and it still fails.
I can't seem to see where I am going here. My simple example seems to work and my real test doesn't.
I also tried brute force and used metaClass to hack an execute closure to set mockres, and that didn't get called either.

Groovy: Implicit call not working on instance variables inside closure

A class implements call method so that it's objects can be called as a method. This works for most of the case but not when the call is being made inside a closure on a object which is instance variable of a class.
To demonstrate the problem, in the code below I've commented the interesting lines with numbers. While most variants result in same output, only the line with comment 5 doesn't work. It throws groovy.lang.MissingMethodException: No signature of method: Client2.instanceVar() is applicable for argument types: () values: [])
Can someone help me understand the reason? Is it a bug?
class CallableObject {
def call() { println "hello" }
}
class Client {
def instanceVar = new CallableObject()
def method() {
def localVar = new CallableObject()
def closure1 = { localVar() }
def closure2 = { instanceVar.call() }
def closure3 = { instanceVar() } // doesn't work
localVar() // 1
instanceVar() // 2
closure1() // 3
closure2() // 4
closure3() // 5
}
}
new Client().method()
I guess this will make it clear.
class CallableObject {
def call() { println "hello" }
}
class Client {
def instanceVar = new CallableObject()
def getInstanceVar() {
println "Getter Called"
instanceVar
}
def method() {
def localVar = new CallableObject()
def closure1 = { localVar() }
def closure2 = { instanceVar.call() }
def closure3 = { this.#instanceVar() } //should work now
localVar() // 1
instanceVar() // 2
closure1() // 3
closure2() // 4
closure3() // 5
}
}
new Client().method()
You will see "Getter Called" printed when closure2() invoked. For a global property to be accessed in the closure inside a method, the getter in called instead. To surmount the error you get, the field instanceVar needs to be accessed directly in order to implicitly use call().

Resources