Could anyone explain me what means sign -> in spock framework?
For exaple we have code like below:
given:
UserService service = Stub()
service.save({ User user -> 'Michael' == user.name }) >> {
throw new IllegalArgumentException("We don't want you here, Micheal!")
}
I know what this code do, but I dont know how role have sign -> in this code.
The Spock Framework assumes a basic level of understanding of the Groovy language and sometimes the more intricate parts of Groovy show up (like in your example).
The -> denotes a closure as described in the Groovy documentation.
For instance, a closure in Groovy could look like this:
def greeting = "Hello"
def sayHiTo = { name -> greeting + " " + name }
println sayHiTo("user3664097")
Related
I'm currently trying to automate the versioning of my maven project with a Jenkins (version 2.190.3) job and following the SemVer. So I have my Jenkinsfile and I'm doing something like that:
script {
def version = "1.2.4"
def pattern = ~/(\d{1,3})\.(\d{1,3})\.\d{1,4}$/
def newVersion = version.replaceFirst(pattern) { _,major,minor -> "${major}.${(minor as int) + 1}.0"}
}
The expectation is to have 1.3.0 in newVersion.
The code seems OK, working on web console but when I'm using Jenkins I have the following error:
java.lang.NullPointerException: Cannot execute null+1
Am I doing something wrong ?
Almost the exact answer to your question is given in this post: Jenkins groovy regex match string : Error: java.io.NotSerializableException: java.util.regex.Matcher
What it comes down to is that the script executed by Jenkins is kind of groovy, but not exactly executed as it is. It is transformed first to a serializable state (can be suspended, saved to file, transported, restored, resumed).
This doesn't work with certain objects that have state, but aren't serializable, including java.util.regex.Matcher, which is working under the hood of your regular expression. If you put this code in a method marked #NonCPS, the code is not transformed, and (more of less) executed as plain groovy.
#NonCPS
def foo() {
def version = "1.2.4"
def pattern = ~/(\d{1,3})\.(\d{1,3})\.\d{1,4}$/
def newVersion = version.replaceFirst(pattern) { _,major,minor -> "${major}.${(minor as int) + 1}.0"}
println "Version ${version} -> new ${newVersion}"
}
script {
foo()
}
I have a test spec, which can be run with a unique data set. The best practice for this is a bit unclear. How should the code below be modified to run with:
#Stepwise
class marktest extends ShopBootStrap {
private boolean useProductionUrl = false
def "Can Access Shop DevLogin page"() {
// DevStartLogin: 'New OE Start' button click
setup:
println System.getProperty("webdriver.chrome.driver")
when:
to ShopDevStartPage
then:
at ShopDevStartPage
}
def "on start enrollment, select 'United States' and click 'continue' button"() {
when: "enter Sponsor ID and click New OE Start"
to ShopDevStartPage
sponsorId.value(ShopDevStartPage.SPONSORID)
NewOEButton.click()
then:
waitFor { NewEnrollmentPage }
}
}
1) data set 1
private boolean useProductionUrl = false
protocol = System.getProperty("protocol") ?: "https"
baseDomain = System.getProperty("base.url") ?: "beta.com"
testPassword = System.getProperty("test.password") ?: "dontyouwish"
2) data set 2
private boolean useProductionUrl = true
protocol = System.getProperty("protocol") ?: "https"
baseDomain = System.getProperty("base.url") ?: "production.com"
testPassword = System.getProperty("test.password") ?: "dywyk"
Generally, to make a test depend on data, use a where block, possibly together with the #Unroll annotation.
However, your case is simply not the best example for a data driven test.
The baseDomain and protocol should rather be set in the GebConfig.groovy, similar to the snippets you provided.
Refer to this section in the Book of Geb, as that is what you are using.
Simple example (in GebConfig.groovy):
environments {
production {
baseUrl = "https://production.com"
}
beta {
baseUrl = "https://beta.com"
}
}
If done this way, your individual tests does not need to care about the environment, as this is already built into Geb.
For example when navigating to pages, their base URL is automatically set.
You did not provide that part of the code in your example (how the pages are defined), so I cannot help you with that directly.
Now, in your case, as far as the "password" is concerned, you could read that from an environment variable or system property, that you set close to where you configure Geb with geb.env or geb.build.baseUrl system properties.
Note I am just considering this for practial reasons without any regards towards secrecy of the password.
You would pick up the variable in the page class that uses it.
Example code in page class:
static content = {
//...
passwordInput = { $('input[type="password"]') }
//...
}
void enterPassword() {
passwordInput.value(System.getProperty('test.password'))
}
To make this work, you need to start your test with the system properties set to correct values.
E.g. if starting directly from the command line, you would add parameters -Dgeb.env=beta -Dtest.password=dontyouwish.
If running from a Gradle task, you would need to add appropriate systemProperty keys and values to that task.
If running from IDE, refer to your IDEs documentation on how to set Java system properties when running a program.
First, I came from a .NET background so please excuse my lack of groovy lingo. Back when I was in a .NET shop, we were using TypeScript with C# to build web apps. In our controllers, we would always receive/respond with DTOs (data xfer objects). This got to be quite the headache every time you create/modify a DTO you had to update the TypeScript interface (the d.ts file) that corresponded to it.
So we created a little app (a simple exe) that loaded the dll from the webapp into it, then reflected over it to find the DTOs (filtering by specific namespaces), and parse through them to find each class name within, their properties, and their properties' data types, generate that information into a string, and finally saved as into a d.ts file.
This app was then configured to run on every build of the website. That way, when you go to run/debug/build the website, it would update your d.ts files automatically - which made working with TypeScript that much easier.
Long story short, how could I achieve this with a Grails Website if I were to write a simple groovy app to generate the d.ts that I want?
-- OR --
How do I get the IDE (ex IntelliJ) to run a groovy file (that is part of the app) that does this generation post-build?
I did find this but still need a way to run on compile:
Groovy property iteration
class Foo {
def feck = "fe"
def arse = "ar"
def drink = "dr"
}
class Foo2 {
def feck = "fe2"
def arse = "ar2"
def drink = "dr2"
}
def f = new Foo()
def f2 = new Foo2()
f2.properties.each { prop, val ->
if(prop in ["metaClass","class"]) return
if(f.hasProperty(prop)) f[prop] = val
}
assert f.feck == "fe2"
assert f.arse == "ar2"
assert f.drink == "dr2"
I've been able to extract the Domain Objects and their persistent fields via the following Gant script:
In scripts/Props.groovy:
import static groovy.json.JsonOutput.*
includeTargets << grailsScript("_GrailsBootstrap")
target(props: "Lists persistent properties for each domain class") {
depends(loadApp)
def propMap = [:].withDefault { [] }
grailsApp.domainClasses.each {
it?.persistentProperties?.each { prop ->
if (prop.hasProperty('name') && prop.name) {
propMap[it.clazz.name] << ["${prop.name}": "${prop.getType()?.name}"]
}
}
}
// do any necessary file I/O here (just printing it now as an example)
println prettyPrint(toJson(propMap))
}
setDefaultTarget(props)
This can be run via the command line like so:
grails props
Which produces output like the following:
{
"com.mycompany.User": [
{ "type": "java.lang.String" },
{ "username": "java.lang.String" },
{ "password": "java.lang.String" }
],
"com.mycompany.Person": [
{ "name": "java.lang.String" },
{ "alive": "java.lang.Boolean" }
]
}
A couple of drawbacks to this approach is that we don't get any transient properties and I'm not exactly sure how to hook this into the _Events.groovy eventCompileEnd event.
Thanks Kevin! Just wanted to mention, in order to get this to run, here are a few steps I had to make sure to do in my case that I thought I would share:
-> Open up the grails BuildConfig.groovy
-> Change tomcat from build to compile like this:
plugins {
compile ":tomcat:[version]"
}
-> Drop your Props.groovy into the scripts folder on the root (noting the path to the grails-app folder for reference)
[application root]/scripts/Props.groovy
[application root]/grails-app
-> Open Terminal
gvm use grails [version]
grails compile
grails Props
Note: I was using Grails 2.3.11 for the project I was running this on.
That gets everything in your script to run successfully for me. Now to modify the println portion to generate Typescript interfaces.
Will post a github link when it is ready so be sure to check back.
So, I have this pretty simple Spec below. I have a class that is not a controller or service or anything like that. It's a Job class. It depends on two services: updateService and directoryTypeService. It runs a Redis async job and it's under /grails-app/jobs folder.
All I want is to make sure that whenever I invoke this job#perform() method (which return type is void), a given dependent method called UpdateService#completeClaiming is invoked, but UpdateService#requestNewPin is not. (Listing is a domain class, by the way).
When I run this Spec, I keep getting an error message saying: "No more calls to 'completeClaiming' expected at this point. End of demands."
What am I doing wrong here? Any wild guesses?
#Mock(Listing)
class SubmissionJobSpec extends Specification {
def directoryTypeServiceMock
def updateServiceMock
def job
def setup(){
job = new SubmissionJob()
directoryTypeServiceMock = mockFor(DirectoryTypeService)
updateServiceMock = mockFor(UpdateService)
job.updateService = updateServiceMock.createMock()
job.directoryTypeService = directoryTypeServiceMock.createMock()
}
def "if the directory is enabled and the pin status is ENTERED, we should call updateService.completeClaiming"() {
given:
directoryTypeServiceMock.demand.isUpdateEnabled { DirectoryType d, Country c -> return true}
new Listing(
location: new Location(country: Country.DE)
).save(failOnError: true, validate: false)
when:
job.perform(Listing.last().id, true)
then:
1 * updateServiceMock.completeClaiming(Listing.last(), true) >> new ListingEvent(output: [success: true])
0 * updateServiceMock.requestNewPin(_ as Listing, true)
}
You seem to be confusing Groovy and Spock mocks. You can't use Spock mocking syntax (e.g. 0 * updateServiceMock.requestNewPin(_ as Listing, true)) for a Groovy mock created with mockFor(). Spock mocks are created using Mock(), Stub() or Spy(). I'm not aware of any good reason to use a Groovy mock in a Spock spec.
I have two class:
class Foo {
String doSomething(String a, String b) {
return 'Not Working'
}
}
class Bar {
String methodIWannaTest() {
return new Foo().doSomething('val1', 'val2')
}
}
And I want to replace 'doSomething' in a test but it dosent work
class BarTests {
#Test
void testMethodIWannaTest() {
Foo.metaClass.doSomething {String a, String b -> return 'Working'}
assert new Bar().methodIWannaTest() == 'Working' //THIS TEST FAIL, return 'Not Working'
}
}
*I know the test doesn't really make sens, it's just to show my point
What do I do wrong ? Is it possible to do it without using 'mockFor' ?
I would suggest you to start the test afresh. Baby Steps is what I follow. :)
Create a new grails app.
Create both Foo and Bar inside src/groovy under a package.
Create unit test case from command prompt. Put the desired test code.
Execute grails test-app
[Grails v2.2.0]
Another alternative is to use Groovy MockFor.
def mock = MockFor(Foo)
mock.demand.doSomething = {String a, String b -> return 'Working'}
mock.use {
assert new Bar().methodIWannaTest() == 'Working'
}
A downside is that there was a bug, making unit tests not clear the mock. This is fixed for 2.2.3.
I found the problem:
First, in my exemple, I forgot the '=' when defining the closure
Foo.metaClass.doSomething {String a, String b -> return 'Working'}
should be
Foo.metaClass.doSomething = {String a, String b -> return 'Working'}
While searching I also found that you cannot replace a method with optionnal parameters by a closure. Probably a bug
I tried this on GGTS 3.2.0 and got the following results.
Copied all the code and ran on Grails 2.2.2: everything worked correctly. However, then I commented out Foo.metaClass.doSomething = {String a, String b -> return 'Working'} line and, surprisingly, the test was still passing successfully. I did more changes and the metaClass just seemed to get "cached" between tests: changes had no effect.
Then I thought if it is possible that Grails were running in interactive mode. Went to Preferences > Groovy > Grails > Grails Launch and found a checkbox 'Keep external Grails running' ticked. Its tooltip even has the following words: 'Warning: experimental feature!'. Unticking that checkbox did the trick and the metaClass no longer got cached between test runs. I am still wondering why an exprimental feature would be turned on by default...