I'm using Grails 3.1.4, I've created some domain object and written unit test.
Tests are executed fine on my computer.
Tests on my computer
But on the other developpers computers and on the continous integration platform, tests fail with exception :
java.lang.IllegalStateException: Either class [ ] is not a domain class or GORM has not been initialized correctly or has already been shutdown. If you are unit testing your entities using the mocking APIs
at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:159)
at org.grails.datastore.gorm.GormEnhancer.findValidationApi(GormEnhancer.groovy:173)
at org.grails.datastore.gorm.GormValidateable$Trait$Helper.currentGormValidationApi(GormValidateable.groovy:120)
at org.grails.datastore.gorm.GormValidateable$Trait$Helper.validate(GormValidateable.groovy:87)
at com.cscinfo.platform.constraint.CascadeValidationConstraint.validateValue(CascadeValidationConstraint.groovy:43)
at com.cscinfo.platform.constraint.CascadeValidationConstraint.processValidateWithVetoing_closure1(CascadeValidationConstraint.groovy:29)
at groovy.lang.Closure.call(Closure.java:426)
at com.cscinfo.platform.constraint.CascadeValidationConstraint.processValidateWithVetoing(CascadeValidationConstraint.groovy:28)
at grails.validation.AbstractVetoingConstraint.validateWithVetoing(AbstractVetoingConstraint.java:33)
at grails.validation.ConstrainedProperty.validate(ConstrainedProperty.java:967)
at org.grails.validation.GrailsDomainClassValidator.validatePropertyWithConstraint(GrailsDomainClassValidator.java:211)
at org.grails.validation.GrailsDomainClassValidator.validate(GrailsDomainClassValidator.java:81)
at org.grails.datastore.gorm.GormValidationApi.doValidate(GormValidationApi.groovy:89)
at org.grails.datastore.gorm.GormValidationApi.validate(GormValidationApi.groovy:161)
at org.grails.datastore.gorm.GormValidateable$Trait$Helper.validate(GormValidateable.groovy:87)
at api.mails.MailSpec.Test la validation d'un mail incorrect 2(MailSpec.groovy:66)
It seems that GORM can't get my domain object.
I can't reproduce the bug on my computer.
Any help or documentation will be appreciated.
Thanks !
The problem was some oject in my Unit test were not mocked.
I put an array of object in my #Mock annotation and now, it works on my continuous integration platform.
#TestFor(SMTPMailerService)
#Mock([Mail, DestinataireMail, PieceJointeMail])
class SMTPMailerServiceSpec extends Specification {
Hope it will help someone !
Related
I have a plain Grails 3.3.2 app. I can run tests just fine with gradle test integrationTest. But when I try to right click and run a test class or a single tests or the entire test suite in IntelliJ, I get:
No GORM implementations configured. Ensure GORM has been initialized correctly
This happens when I run them as jUnit tests.
If i try to run as Grails tests, I get:
No tests found for given includes
I have tried to clean the build and reset caches in IntelliJ, but nothing seems to help. Unfortunately I don't know what I've done to put Grails + IntelliJ in this state either. It used to work, but now it doesn't, and I'm not sure what has changed.
I found a "fix", sort of.
I edited the #IntegrationTest annotation on my test class from:
#Integration
to
#Integration(applicationClass = Application.class)
And now it works again.
Interestingly, if I change it back to just #Integration, it still works. But if I run a clean, and rerun, it stops working. So something is definitely wonky here.
EDIT: I wrote the following test case:
CompilerConfiguration configuration = new CompilerConfiguration()
configuration.setTolerance(1)
println new File("src/integration-test/groovy/my/package/Mytest.groovy").isFile()
// true
def source = new SourceUnit(
new File("src/integration-test/groovy/my/package/MyTest.groovy"),
configuration,
null,
new ErrorCollector(configuration))
println source
// org.codehaus.groovy.control.SourceUnit#19bbb216
println source.source
// org.codehaus.groovy.control.io.FileReaderSource#6cfac0bd
println source.source.URI
// file:/path/to/my/app/src/integration-test/groovy/my/package/MyTest.groovy
println MainClassFinder.searchMainClass(source.source.URI)
// null
The AST transformation #Integration runs MainClassFinder.searchMainClass when the applicationClass property is not set. So this seems to indicate that it for some reason isn't able to automatically find the application class for my app based on the integration test. Then again, I'm not really sure which source unit it actually gets when it runs, so my test case might not be realistic.
I am trying to get my geb-spock functional tests to run in a specified order because SpecA will create data required for SpecB during its run.
This question is about running the specifications in order, not the individual test methods within the specification.
I have tried changing the specification name to indicate execution order but that didn't work. I found a solution where a Test Suite was used, and the tests were added to the suite in order, but I can't find how to make a test suite work in Grails.
Explicitly specifying them as grails test-app functional: SpecA SpecB , is not a long term option, as more specs will be added.
For sequential or whatever the sequence you want to run your tasks, I do the following thing in my build.gradle file:
def modules = ["X", "Y", "Z", "ZZ"]
if (modules.size() > 1) {
for(j in 1 .. modules.size()-1 ) {
tasks[modules[j]].mustRunAfter modules[values[j-1]]
}
}
Hope that helps. Cheers!
Not really an answer to your question but a general advice - don't do this. Introducing data setup dependencies between test classes will make your suite brittle in the long run. Reasoning about what the state is at a given point will get harder and harder as the amount of tests grows and the global state size with it. Later on hanging a test or introducing a new one might break many tests downstream. This is just asking for trouble.
Ideally, you want to setup the data needed by a test immediately before that test and tear it down afterwards. Grails Remote Control plugin and test data fixture builders are your friends here.
You should define your initialization code in a single place, and if it's shared between both Specs, it may be a good idea to create a superclass with methods you can call in each Spec's set up methods, or a whole class devoted to declare testing methods to reuse.
In any case, the purpose of a unit test is only to test a single functionality, and it shouldn't be responsible of setting up other tests as well.
In a grails project (version 2.3.7) , i have an integration test using Spock :
class SimpleIntegrationTests extends IntegrationSpec{
void "test an action from controller to database"(){...}
}
This integration test launch a batch with Spring Batch. Spring batch does not accept when a batch is launched from an existing transaction :
java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again
So i tell my integration test to run without transaction, with :
static transactional = false
Doing this, the test runs with success.
But there are other integration tests in my project, which need transactions to run correctly.
And the instruction "transactionnal = false" in my test class is not confined to this test class, but affects all other integration tests triggered after my test class.
I understood there is an alphabetically execution order for the tests. So i know that if i rename my test class to be the last test class to run, it works fine, and all my tests are successful. But i think it s not an ideal answer to the problem.
So my question is : how to define that a test class is non transactionnal, in a manner that does not affect other integration tests ?
I know this is an old question and I imagine you've found a solution already, but as a work around I think you need to explicitly specify static transactional = true on integration tests that you still want to be transactional. We've had a similar issue with our Grails 2.3.7 test suite...
The following artical code works in 'grails console'. But when I try to run it in STS its giving compile error for the domain class.
http://timsporcic.github.io/GORM-Recipes/
Is it possible to run in STS, I want to test to GORM methods before using it in contolers. even console command from STS is not working.
trying to run like this:
class Test {
static main(args) {
new BootStrap().init()
println Person.get(1)
}
}
thanks
Run as > Groovy Script will not work. grails console works different, because you have you application fully initialized (same for run-app and test-app).
If you want to test your BootStrap class I suggest you to create one integration test. This will also ensure that, if you change your class, the logic still works.
I'm a grails newbie (and a groovy newbie), and I'm working through some grails tutorials. As a new user, the grails shell is a really useful little tool for me, but I can't figure out how to make it see my classes and objects. Here's what I'm trying:
% grails create-app test
% cd test
% grails create-domain-class com.test.TestObj
% grails shell
groovy:000> new TestObj()
ERROR org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, groovysh_evaluate: 2: unable to resolve class TestObj
I was under the impression that the grails shell could see all of the controllers, services, and domain objects. What's up with this? Do I need to do something else here?
I tried one other thing:
groovy:000> foo = new com.test.TestObj();
===> com.test.TestObj : null
groovy:000> foo.save
ERROR groovy.lang.MissingPropertyException: No such property: save for class: com.test.TestObj
What am I doing wrong?
EDIT: Okay, I saw the answers about using the full name and also using .save() instead of .save. But what about this one?
groovy:000> new com.test.TestObj().save()
ERROR org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
What'd I do wrong this time?
I second Burt's advice to use the console instead of the shell. Regarding the exception:
groovy:000> new com.test.TestObj().save()
ERROR org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
Can you try explicitly running this code with a transaction:
import com.test.TestObj
TestObj.withTransaction{ status ->
TestObj().save()
}
You need the package since it's possible (but not a good idea) to have two domain classes with the same name in different packages.
For the 2nd session it should be foo.save(), not foo.save.
I prefer the console, it's a lot easier to work with. Run 'grails console' and the Swing app will start. It's a little different from the regular Groovy console in that it's got an implicit 'ctx' variable available which is the Spring application context. You can use that to access services and other Spring beans via "ctx.getBean('fooService')"
you will have to import com.test.TestObj or reference it by new com.test.TestObj() as you have shown.
Note that 'save' is not a propery but a dynamic method that Grails decorates the domain class with at runtime.
groovy:000> foo = new com.test.TestObj();
===> com.test.TestObj : null
groovy:000> foo.save()
===> com.test.TestObj : 2
groovy:000>