I have a problem while running fixtureLoader.load in BootStrap.groovy.
import grails.plugin.fixtures.FixtureLoader
class BootStrap {
def fixtureLoader
def init = { servletContext ->
environments {
test {
fixtureLoader.load {
build {
device1(Device, name: "device1")
device2(Device, name: "device2")
device3(Device, name: "device3")
}
}
}
}
}
def destroy = {
}
}
When Grails starts integration test phase, the load is executed. Then when Grails starts functional test phase, the load is executed another time without cleaning previous execution.
Thats means:
If I run with "test-app functional:" or "test-app integration:" everything is all right.
If I run with "test-app" both functional and integration tests are executed.
This is the JSON representation of data at functional test phase (running with "test-app"):
[[name:device3], [name:device2], [name:device1],[name:device3], [name:device2], [name:device1]]
This is same JSON representation of data at functional test phase (running with "test-app functional:")
[[name:device3], [name:device2], [name:device1]]
How to avoid this duplicates?
Thanks in advance
The default test database is a non-persistant in-memory hsqldb that gets discarded at the end of your tests, but changes to it will carry over between test phases. Also, integration testing rolls back changes after each test, but this doesn't apply to database changes made in Bootstrap.groovy.
One simple way to fix this is to simple check for the existence of the fixtures before trying to create them. For example:
environments {
test {
if (Device.count() == 0) {
// build fixtures
}
}
}
Another possible solution is to use separate databases for integration and functional tests. There's an example of how to do it at http://www.redtoad.ca/ataylor/2011/02/setting-grails-functional-test-database/
Related
Whenever I am trying to run the tagged test cases in jenkins, they are getting skipped with the message
WARN org.testng.internal.Utils - The test method 'testRunner.TestRunner.feature' will be skipped since its data provider 'features' returned an empty array or iterator.
but the same test cases are getting executed and passed in my local machine. I have integrated cucumber with maven and testNG
Below is my test runner file
#CucumberOptions(features = { "src/test/java/com/test_Cases_FeatureFiles" },
glue = {"stepDefs"},
plugin = { "pretty","html:target/cucumber-html-report","com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:" },
monochrome = true,
tags = "#FileDownload_Tests")
public class TestRunner extends AbstractTestNGCucumberTests {
}
Please suggest a way out for this issue.
I have a grails 3.1.x project with lots of controllers and I use spock for testing the controllers.
I use a command pattern for my controllers so each action takes a command object.
An example for such a controller :
class PlaygroundController {
public Object pg(PgCO pgco) {
String s = null
if (pgco.one) {
s = pgco.one
}
if (pgco.two) {
s = pgco.two
}
render view: 'pg', model: [resultat: s]
}
}
I have a simple spock test case:
void "pg"() {
given:
PgCO pgCO = new PgCO()
pgCO.one = 'TEST'
when:
controller.pg(pgCO)
then:
view == '/playground/pg'
model
model.resultat == 'TEST'
}
This test runs fine, but when i run a jacocoTestReport it shows that my coverage is way below 50% , it's fine that it's not fully covered since I'm only covering one branch.
But the report contains loads of "missed instructions" on methods that I have no source code for.. specially there is a shadow pg() method that doesn't take any parameters. Grails injects this method, but I will never call that method from my tests since I use the command object version of the same method. this method but also a lot of other methods coming from grails controller framework.
Isn't there anyw ay to tell jacoco that it's only the "source code" that needs to be checked for coverage ?
I've tried specifying exact source dirs, but this doesn't help
Here's an image of the coverage report:
coverage report
I have a daily simple project just enabling the jacoco plugin, and running latest jacoco :
jacoco {
toolVersion = "0.7.5.201505241946"
}
Have anyone else a solution to this ?
Help!
Our plugin project integration tests should hit the database specified in the datasource.groovy, but for some reason they ignore it, and do it in memory.
Its a plugin which provides the core services (i.e. DB access) to several grails apps which are each a grails application.
Datasource.groovy looks like this:
dataSource {
pooled = true
driverClassName = "com.mysql.jdbc.Driver"
dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
}
environments {
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:mysql://127.0.0.1:3306/db"
username = "someuser"
password = "somepass"
}
}
test {
dataSource {
dbCreate = "update"
url = "jdbc:mysql://127.0.0.1:3306/db"
username = "someuser"
password = "somepass"
}
}
production {
dataSource {
}
}
}
The test (SiteIntegrationSpec.goovy)
import grails.test.mixin.TestFor
import grails.test.spock.IntegrationSpec
#TestFor(Site)
class SiteIntegrationSpec extends IntegrationSpec {
static transactional = false
def setup() {
}
def cleanup() {
}
void "test something"() {
when:
Site site
site = new Site(name: "asdf", description: "asdfsd").save(failOnError: true)
then:
site.id == 3
when:
Site site2 = Site.get(1L)
then:
site2.name == "root"
}
}
Data already existing in the site table:
ID name description
1 root root
2 test test
The first test should insert a record which will happen to have an ID of 3. It actually inserts with an ID of 1, i.e. its not seeing or hitting the test database, its using some mock or internal db which is not defined anywhere.
The second test fails as instead of retrieving "root" it retrieves "asdf"
What I have tried:
creating a separate DB for test. Didn't help.
specifying -Dgrails.env=test when running tests. Didn't help
running the tests with the DB down. This correctly fails with cant create pool type exception.
changing the test datasource password to an incorrect one - this correctly throws an exception.
grails -Dgrails.env=test test-app com.me.myproject.SiteIntegrationSpec --stacktrace --verbose
So grails is connecting to the test datasource, but then the integration tests are not using it!
Any ideas?
Edit: Site is a domain object:
class Site {
String name
String description
}
Plugin DataSource.groovy files aren't included in the plugin zip, and if you somehow manually or programmatically include them, they'll be ignored. The same goes for Config.groovy, UrlMappings.groovy, and BootStrap.groovy. In general when something is usable from a plugin, if the application has a file with the same name and location, it overrides the plugin's file, so that would keep this from working also.
You could define a dataSource bean in your plugin's doWithSpring that replaces the one Grails creates based on DataSource.groovy that uses values from a file that exists in the plugin zip, or that is located in the application if that makes sense. Note that there are really 3 DataSource beans and two of them are proxies of the "real" one, so you need to define yours as dataSourceUnproxied so the other two proxy yours and retain the behavior that they add.
Another thing that you will need to fix once you resolve this is your use of unit test annotations in an integration test. Never use Mock, TestFor, or any unit test mixin annotation or base class, since their purpose is to establish a fairly realistic environment that makes up for Spring, Hibernate, installed plugins, and lots of Grails functionality not being available, but in an integration test they are available, and the unit test stuff will stomp on the real instances.
Also - why are you using static transactional = false? This disables an important integration test feature where all of your test methods run in a transaction that is rolled back at the end of the tests pass or fail. This ensures that nothing you do in a test influences other tests - everything is independent. If you disable this, you need to undo all of the changes, and it's easy to miss some and introduce false negatives or worse - false positives - into your tests.
I have a service method that locks a database row.
public String getNextPath() {
PathSeed.withTransaction { txn ->
def seed = PathSeed.lock(1)
def seedValue = seed.seed
seed.seed++
seed.save()
}
}
This is how my spock test looks like:
void "getNextPath should return a String"() {
when:
def path = pathGeneratorService.getNextPath()
then:
path instanceof String
}
It's just a simple initial test. However I get this error when I run the test:
java.lang.UnsupportedOperationException: Datastore [org.grails.datastore.mapping.simple.SimpleMapSession] does not support locking.
at org.grails.datastore.mapping.core.AbstractSession.lock(AbstractSession.java:603)
at org.grails.datastore.gorm.GormStaticApi.lock_closure14(GormStaticApi.groovy:343)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormStaticApi.lock(GormStaticApi.groovy:342)
at com.synacy.PathGeneratorService.getNextPath_closure1(PathGeneratorService.groovy:10)
at org.grails.datastore.gorm.GormStaticApi.withTransaction(GormStaticApi.groovy:712)
at com.synacy.PathGeneratorService$$EOapl2Cm.getNextPath(PathGeneratorService.groovy:9)
at com.synacy.PathGeneratorServiceSpec.getNextPath should return a String(PathGeneratorServiceSpec.groovy:17)
Does anyone have any idea what this is?
The simple GORM implementation for Unit tests does not support some features, such as locking. Moving your test to an integration test will use the full implementation of GORM instead of the simple implementation used by unit tests.
Typically when you find yourself using anything more than the very basic features of GORM you will need to use integration tests.
Updated 10/06/2014
In more recent versions of Grails and GORM there is now the HibernateTestMixin which allows you to test/use such features in Unit tests. Further information can be found in the documentation.
As a workaround, I was able to get it working by using Groovy metaprogramming. Applied to your example:
def setup() {
// Current spec does not test the locking feature,
// so for this test have lock call the get method
// instead.
PathSeed.metaClass.static.lock = PathSeed.&get
}
I'm writing the Integration test for a Quartz Job in a grails application.
I've the Job in grails-app/jobs folder, and if I start the application it works. The problem is that I want to get it in an integration test, but the autowire won't work. The test is like:
class MyJobTest{
MyJob myJob
def setUp(){
assert myJob != null
}
def testExecute(){
//test logic
}
}
but it fails because myJob is null...some help?
Quartz Jobs are not autowired like services are under the test environment. The documentation for the Quartz job also explicitly states that by default it will not execute on schedule under the test environment (you could change that if you want to but I wouldn't). I would just instantiate myJob = new MyJob() in your setUp and call the execute() method to test it. If you're trying to test the triggers you may want to find a way to look at what is inside the triggers {} maybe inspecting the metaClass?
EDIT IN RESPONSE TO COMMENT:
I've never gotten the services out of the application context so that might work. The way I would probably test it is as follows:
Assuming your class looks something like this:
class MyJob {
def myServiceA
def myServiceB
def execute() {
if(myJobLogicToDetermineWhatToDo) {
myServiceA.doStuff(parameter)
} else {
myServiceB.doStuff(parameter)
}
}
}
What you're really wanting to test here is the myJobLogicToDetermineWhatToDo. I would assume that you have (or can easily write) integration and/or unit tests against your services myServiceA and myServiceB to ensure that they are working correctly. I would then write unit tests to test the logic/wiring of your Job to the appropriate service.
#Test
void routeOne() {
def job = new MyJob()
def myServiceA = new Object()
def expectedParameter = "Name"
def wasCalled = false
myServiceA.metaClass.doStuff = {someParameter ->
assert expectedParameter == someParameter
wasCalled = true
}
job.myServiceA = myServiceA
//Setup data to cause myServiceA to be invoked
job.execute()
assert wasCalled
}
Then repeat this process for all of the routes you have through your Job. This way you can isolate your tests down to the smallest part possible and test the logic of the object that you're invoking not the services it is using. I would assume you're using a service because the logic in there is being used by another part of the system. If you're testing the service through this job and for some reason the job goes away then you have to re-write your tests to invoke the service directly. The way that I've proposed you have tests testing the service directly and tests that mock out those service calls. If the job goes away you would simply delete the tests associated with it and you won't loose any test coverage. Kinda long winded but that's how I would approach testing it.