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.
Related
I am trying to test a class that will call another web service to fetch data if a null value is provided. My JUnit + Mockito test works great, but I cannot get my Spock test to match in the then: block. The error returned during the Spock test is:
Suppressed: java.lang.NullPointerException: Cannot invoke method map() on null object
Which is because my mocked method is not matching, and therefore returns null.
Spock test (not working)
class MySpec extends Specfication {
def mockCollaboratingService = Mock(CollaboratingService)
def service = new MyService(collaboratingService: mockCollaboratingService)
def "should call another service if the provided start value equals null"() {
given:
def id = 123
def startDate = null
when: "the service is called"
def result = service.getTransactions(id, startDate)
then:
1 * mockCollaboratingService.getData(id) >> Mono.just(new SomeMockResponse(key: "123"))
StepVerifier
.create(result)
.consumeNextWith({
// assertions here
})
.verifyComplete()
}
}
JUnit + Mockito (working)
class AnotherSpec {
def mockCollaboratingService = Mockito.mock(MockCollaboratingService)
def service = new MyService(collaboratingService: mockCollaboratingService)
#Test
#DisplayName("should call the statement service if the given start date is null")
void shouldCallStatementServiceIfStartDateEqualsNull() {
def id = 123
def startDate = null
// and some fake data returned from the api
Mockito.when(mockCollaboratingService.getData(id)).thenReturn(Mono.just(new SomeMockResponse(key: "123")))
//when
def result = service.getTransactions(id, null)
//then
StepVerifier
.create(result)
.consumeNextWith({
Mockito.verify(mockStatementService, Mockito.times(1)).getLastStatement(enterpriseToken)
assert it.transactionId == 123
})
.verifyComplete()
}
}
Spock handles mocking differently than mockito, have a look at combining mocking and stubbing. Furthermore, all interactions must be finished before the then block, as Spock verifies them as first thing. With reactor, it is actually StepVerifier that is executing the code. The line def result = service.getTransactions(id, startDate) only creates a cold Mono/Flux, but doesn't to anything.
So, you have to reorder your tests slightly.
class MySpec extends Specfication {
def mockCollaboratingService = Mock(CollaboratingService)
def service = new MyService(collaboratingService: mockCollaboratingService)
def "should call another service if the provided start value equals null"() {
given:
def id = 123
def startDate = null
when: "the service is called"
def result = service.getTransactions(id, startDate)
and: "code is executed"
StepVerifier
.create(result)
.consumeNextWith({
// no explicit mock assertions necessary
assert it.transactionId == 123
})
.verifyComplete()
then:
1 * mockCollaboratingService.getData(id) >> Mono.just(new SomeMockResponse(key: "123"))
}
}
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
I am using geb spock. I am trying to read the system variable from GebConfig file, however it returns the null value.
Below is my GebConfig.groovy file.
def final DEFAULT_BROWSER = "chrome"
def final DEFAULT_LANGUAGE = "nl" //"en" or "nl"
def browser = System.getProperty("geb.env")
//Default browser
if (!correctBrowser(browser)) {
browser = DEFAULT_BROWSER
}
def envLang = System.getProperty("geb.env.lang")
//Default language
if (!correctLanguage(envLang)) {
envLang = DEFAULT_LANGUAGE
}
System.setProperty("geb.env.lang", envLang)
System.setProperty("geb.env", browser)
environments {
driver = { getDriver(browser, envLang) }
}
Below is my spec file where I am trying to get the language value in a variable.
#Stepwise
class TC001_SMO_Scenario_Spec extends GebReportingSpec {
#Shared
def lang = System.getProperty("geb.env.lang")
def "Step 1: Perform Login"() {
when: "Load File"
to WUPage
then: " File loaded successfully"
println " Getting data from Geb Config File: " + lang
}
}
Can you please help me how to do this, as this is very important for me to access and store it in a variable. Thanks
The problem is your #Shared variable. The Geb manual says:
(...) declare a #Shared field. Again it’s best to initialize the field right at the point of declaration. (Semantically, this is equivalent to initializing the field at the very beginning of the setupSpec() method.)
The thing is, setupSpec() runs before GebConfig is evaluated. You can see it if you add this to the end of your GebConfig:
println "Finished evaluating GebConfig"
Then run this Geb specification (I have wrapped the variable assignments into closures and added print statements, then I am evaluating the closures so as to make the assignments work):
package de.scrum_master.stackoverflow
import geb.spock.GebReportingSpec
import spock.lang.Shared
class GebConfigIT extends GebReportingSpec {
#Shared
def sharedLang = {
println "Initialising sharedLang"
System.getProperty("geb.env.lang")
}()
def normalLang = {
println "Initialising normalLang"
System.getProperty("geb.env.lang")
}()
def setup() {
println "sharedLang = $sharedLang"
println "normalLang = $normalLang"
}
def foo() {
expect:
!sharedLang
normalLang
}
def bar() {
expect:
!sharedLang
normalLang
}
}
Initialising sharedLang
Finished evaluating GebConfig
Initialising normalLang
sharedLang = null
normalLang = nl
Initialising normalLang
Finished evaluating GebConfig
sharedLang = null
normalLang = nl
Can you see how sharedLang is initialised only once at the very beginning, before GebConfig even gets a chance to kick in?
Bottom line: Just remove #Shared from your code. It is over-used by most people anyway, they think they save time this way for cheap resources and tamper with their clean fixture setups. #Shared really is only for very expensive resources and very exceptional cases.
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.
Let's say I have a DSL like this
setup {name = "aDSLScript"}
println "this is common groovy code"
doStuff {println "I'm doing dsl stuff"}
One would have a delegating class implementing the methods 'setup' and 'doStuff' usually. Beside, one could write common Groovy code to be executed (println...).
What I am searching for, is a way to execute this in two steps. In the first step only the setup method should be processed (neither println). The second step handles the other parts.
At the moment, I have two delegating classes. One implements 'setup' the other one implements 'doStuff'. But both execute the println statement, of course.
You can create a single class to intercept the method calls from the script and let it coordinate the following method invoke. I did it through reflection, but you can go declarative if you want. These are the model and script classes:
class FirstDelegate {
def setup(closure) { "firstDelegate.setup" }
}
class SecondDelegate {
def doStuff(closure) { "secondDelegate.doStuff" }
}
class MethodInterceptor {
def invokedMethods = []
def methodMissing(String method, args) {
invokedMethods << [method: method, args: args]
}
def delegate() {
def lookupCalls = { instance ->
def invokes = instance.metaClass.methods.findResults { method ->
invokedMethods.findResult { invocation ->
invocation.method == method.name ?
[method: method, invocation: invocation] : null
}
}
invokes.collect { invoked ->
invoked.method.invoke(instance, invoked.invocation.args)
}
}
return lookupCalls(new FirstDelegate()) + lookupCalls(new SecondDelegate())
}
}
Here be scripts and assertions:
import org.codehaus.groovy.control.CompilerConfiguration
def dsl = '''
setup {name = "aDSLScript"}
println "this is common groovy code"
doStuff {println "Ima doing dsl stuff"}
'''
def compiler = new CompilerConfiguration()
compiler.scriptBaseClass = DelegatingScript.class.name
def shell = new GroovyShell(this.class.classLoader, new Binding(), compiler)
script = shell.parse dsl
interceptor = new MethodInterceptor()
script.setDelegate interceptor
script.run()
assert interceptor.invokedMethods*.method == [ 'setup', 'doStuff' ]
assert interceptor.delegate() ==
['firstDelegate.setup', 'secondDelegate.doStuff']
Notice I didn't bothered intercepting println call, which is a DefaultGroovyMethods thus, a little more cumbersome to handle.
Also having the class MethodInterceptor implementing the method delegate() is not a good idea, since this allows the user-defined script to call it.
I found a way to split up execution of the DSL script. I used a CompilationCustomizer to remove every statement from AST except the doFirst{}. So the first run will only execute doFirst. The second run does everything else. Here's some code:
class DoFirstProcessor {
def doFirst(Closure c) {
c()
}
}
class TheRestProcessor {
def doStuff(Closure c) {
c()
}
def methodMissing(String name, args) {
//nothing to do
}
}
def dsl = "
println 'this is text that will not be printed out in first line!'
doFirst { println 'First things first: e.g. setting up environment' }
doStuff { println 'doing some stuff now' }
println 'That is it!'
"
class HighlanderCustomizer extends CompilationCustomizer {
def methodName
HighlanderCustomizer(def methodName) {
super(CompilePhase.SEMANTIC_ANALYSIS)
this.methodName = methodName
}
#Override
void call(SourceUnit sourceUnit, GeneratorContext generatorContext, ClassNode classNode) throws CompilationFailedException {
def methods = classNode.getMethods()
methods.each { MethodNode m ->
m.code.each { Statement st ->
if (!(st instanceof BlockStatement)) {
return
}
def removeStmts = []
st.statements.each { Statement bst ->
if (bst instanceof ExpressionStatement) {
def ex = bst.expression
if (ex instanceof MethodCallExpression) {
if (!ex.methodAsString.equals(methodName)) {
removeStmts << bst
}
} else {
removeStmts << bst
}
} else {
removeStmts << bst
}
}
st.statements.removeAll(removeStmts)
}
}
}
}
def cc = new CompilerConfiguration()
cc.addCompilationCustomizers new HighlanderCustomizer("doFirst")
cc.scriptBaseClass = DelegatingScript.class.name
def doFirstShell = new GroovyShell(new Binding(), cc)
def doFirstScript = doFirstShell.parse dsl
doFirstScript.setDelegate new DoFirstProcessor()
doFirstScript.run()
cc.compilationCustomizers.clear()
def shell = new GroovyShell(new Binding(), cc)
def script = shell.parse dsl
script.setDelegate new TheRestProcessor()
script.run()
I did another variation of this where I execute the DSL in one step. See my blog post about it: http://hackserei.metacode.de/?p=247