Giter Club home page Giter Club logo

grails-testing-support's Introduction

grails-testing-support's People

Contributors

alvarosanchez avatar fergusmcglynn avatar graemerocher avatar guillermocalvo avatar ilopmar avatar jameskleeh avatar jessestuart avatar jprinet avatar matrei avatar niravassar avatar puneetbehl avatar renovate-bot avatar renovate[bot] avatar sbglasius avatar sdelamo avatar yuri1969 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grails-testing-support's Issues

groovydoc throws NoClassDefFoundError: picocli/CommandLine$ParameterException

$ ./gradlew groovydoc
To honour the JVM settings for this build a new JVM will be forked. Please consider using the daemon: https://docs.gradle.org/5.0/userguide/gradle_daemon.html.
Daemon will be stopped at the end of the build stopping after processing

> Task :groovydoc FAILED
Exception in thread "main" java.lang.NoClassDefFoundError: picocli/CommandLine$ParameterException
        at java.lang.Class.getDeclaredConstructors0(Native Method)
        at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
        at java.lang.Class.getDeclaredConstructors(Class.java:2020)
        at org.codehaus.groovy.reflection.CachedClass$2$1.run(CachedClass.java:88)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:86)
        at org.codehaus.groovy.reflection.CachedClass$2.initValue(CachedClass.java:81)
        at org.codehaus.groovy.util.LazyReference.getLocked(LazyReference.java:50)
        at org.codehaus.groovy.util.LazyReference.get(LazyReference.java:37)
        at org.codehaus.groovy.reflection.CachedClass.getConstructors(CachedClass.java:310)
        at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:218)
        at groovy.lang.MetaClassImpl.<init>(MetaClassImpl.java:228)
        at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createNormalMetaClass(MetaClassRegistry.java:171)
        at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:161)
        at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:144)
        at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:288)
        at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:331)
        at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:271)
        at org.codehaus.groovy.runtime.InvokerHelper.getMetaClass(InvokerHelper.java:969)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.createCallConstructorSite(CallSiteArray.java:86)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:237)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:249)
        at org.codehaus.groovy.tools.groovydoc.Main.main(Main.groovy:62)
Caused by: java.lang.ClassNotFoundException: picocli.CommandLine$ParameterException
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        ... 24 more

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':groovydoc'.
> Process 'command '/Users/sdelamo/.sdkman/candidates/java/8.0.191-oracle/bin/java'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.0/userguide/command_line_interface.html#sec:command_line_warnings

Problem Testing Data Services

(moving issue from grails/grails-data-mapping#1020 to here)

See https://github.com/jeffbrown/servicetestproblem

Domain:

package servicetestproblem

class Person {
    String name
}

Data Service:

package servicetestproblem

import grails.gorm.services.Service

@Service(Person)
abstract class PersonService {
    abstract List<Person> list()
}

Unit test:

package servicetestproblem

import grails.testing.gorm.DataTest
import grails.testing.services.ServiceUnitTest
import spock.lang.Specification

class PersonServiceSpec extends Specification implements ServiceUnitTest<PersonService>, DataTest {

    def setupSpec() {
        mockDomain Person
    }

    void 'first test'() {
        expect:
        service.list().size() == 0
    }

    void 'second test'() {
        expect:
        service.list().size() == 0
    }
}

There is no reason to have a unit test like that of course but this is a simple example that demonstrates the problem. The second test method will fail with the following:

Condition failed with Exception:

service.list().size() == 0
|
java.lang.reflect.InvocationTargetException

	at servicetestproblem.PersonServiceSpec.second test(PersonServiceSpec.groovy:20)
Caused by: java.lang.reflect.InvocationTargetException
	at grails.testing.services.ServiceUnitTest$Trait$Helper.mockArtefact(ServiceUnitTest.groovy:66)
	at org.grails.testing.ParameterizedGrailsUnitTest$Trait$Helper.getArtefactInstance(ParameterizedGrailsUnitTest.groovy:48)
	at grails.testing.services.ServiceUnitTest$Trait$Helper.getService(ServiceUnitTest.groovy:83)
	... 1 more
Caused by: java.lang.IllegalStateException: Could not register object [servicetestproblem.$PersonServiceImplementation@42339ea2] under bean name 'personService': there is already object [servicetestproblem.$PersonServiceImplementation@42339ea2] bound
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.registerSingleton(DefaultSingletonBeanRegistry.java:130)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerSingleton(DefaultListableBeanFactory.java:936)
	at grails.testing.gorm.DataTest$Trait$Helper.mockDataService(DataTest.groovy:101)
	... 4 more

Controller unit test failure when the request body is empty and is read directly

Implementing complete GraphQL support involves reading the request body and considering it as the query for one special case. In a controller, this means using request.reader.text.

def index() {
    def body = request.reader.text
    respond body
}

In a test class the controller method is called multiple times as there are multiple tests.

def "test"() {
    when:
    controller.index()

    then:
    true
}

def "test2"() {
    when:
    controller.index()

    then:
    true
}

This is a problem when the body is empty. When executing the second test, it fails with java.io.IOException: Stream closed. The tests are not independent.

Please note that when the body is not empty, i.e.
request.json = [hello: "world"]
the tests pass.

Please also note that replacing request.reader.text with request.JSON in the controller causes the tests to pass. This is specifically for reading the body text.

How to test configuration manipulation?

I have probably misunderstood the Manipulating Configuration docs.

Given this service:

import grails.config.Config
import grails.core.support.GrailsConfigurationAware
import groovy.transform.CompileStatic

@CompileStatic
class SignupService implements GrailsConfigurationAware {

    Boolean allowSignup

    @Override
    void setConfiguration(Config co) {
        allowSignup = co.getProperty('mc.allow.signup', Boolean)
    }

    boolean isSignupAllowed() {
        allowSignup
    }
}

and this test:

import grails.testing.services.ServiceUnitTest
import spock.lang.Specification

class SignupServiceSpec extends Specification implements ServiceUnitTest<SignupService> {

    Closure doWithConfig() {{ config ->
        config.mc.allow.signup = true
    }}

    def "singup is allowed if configuration parameter is set"() {
        expect:
        service.isSignupAllowed()
    }
}

I expected the previous test to pass but it fails.

Grails Specification test unable identify Domain in in-place plugin as Domain object

I am trying to build a plugin with multitenency feature that carries all the domain object so that it can be shared across multiple grails based web-application, but on writing a simple unit-test I am seeing that the Unit-test denies to identify the Domain class in the plugin as a domain at all.
If I run the same test by linking it with the Domain object in the project itself instead of Plugin, everything works fine, I cannot have the test placed in plugin itself as the heavy implementation will be on the specific service end, any idea on it, below is the code snippet, where Benefit is the domain obect that lies inside the inplace plugin:-

package test

import com.common.domain.Benefit
import grails.test.hibernate.HibernateSpec
import grails.testing.services.ServiceUnitTest
import org.grails.datastore.mapping.config.Settings
import org.grails.datastore.mapping.multitenancy.resolvers.SystemPropertyTenantResolver

class TestServiceSpec extends HibernateSpec implements ServiceUnitTest<TestService>{

    Class<?>[] getDomainClassesToMock(){
        return [Benefit] as  Class[]
    }

    @Override
    Map getConfiguration() {
        [(Settings.SETTING_MULTI_TENANT_RESOLVER_CLASS): SystemPropertyTenantResolver]
    }

    def setup() {
        System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, 'vendor1') //
    }


    def cleanup() {
        System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, '')
    }

    void "test something"() {
        expect:"fix me"
            service.serviceMethod()
            true == true
    }
}

here is the service

.
.
import com.common.domain.Benefit

@Transactional
@CurrentTenant
@CompileStatic
class TestService {

    def serviceMethod() {
       def something = Benefit.findAll()
        println something
        return something

    }
}

Following is the error I am gettin on the end of the unit test

Either class [com.common.domain.Benefit] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
java.lang.IllegalStateException: Either class [com.common.domain.Benefit] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
	at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:472)
	at org.grails.datastore.gorm.GormEnhancer.findDatastore(GormEnhancer.groovy:354)
	at org.grails.datastore.gorm.GormEnhancer.findTenantId(GormEnhancer.groovy:268)
	at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:299)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.currentGormStaticApi(GormEntity.groovy:1368)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.findAll(GormEntity.groovy:689)
	at org.grails.datastore.gorm.GormEntity$Trait$Helper.findAll(GormEntity.groovy:688)
	at test.TestService.$tt__serviceMethod(TestService.groovy:15)
	at test.TestService._mt__serviceMethod_closure3(TestService.groovy)
	at groovy.lang.Closure.call(Closure.java:418)
	at groovy.lang.Closure.call(Closure.java:434)
	at grails.gorm.transactions.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:94)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
	at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
	at test.TestService.serviceMethod_closure1(TestService.groovy)
	at groovy.lang.Closure.call(Closure.java:418)
	at groovy.lang.Closure.call(Closure.java:434)
	at grails.gorm.multitenancy.Tenants.withId_closure2$_closure6(Tenants.groovy:265)
	at org.grails.orm.hibernate.GrailsHibernateTemplate$1.doInHibernate(GrailsHibernateTemplate.java:153)
	at org.grails.orm.hibernate.GrailsHibernateTemplate.doExecute(GrailsHibernateTemplate.java:299)
	at org.grails.orm.hibernate.GrailsHibernateTemplate.execute(GrailsHibernateTemplate.java:243)
	at org.grails.orm.hibernate.GrailsHibernateTemplate.executeWithNewSession(GrailsHibernateTemplate.java:150)
	at org.grails.orm.hibernate.GrailsHibernateTemplate.executeWithExistingOrCreateNewSession(GrailsHibernateTemplate.java:209)
	at org.grails.orm.hibernate.AbstractHibernateDatastore.withNewSession(AbstractHibernateDatastore.java:369)
	at grails.gorm.multitenancy.Tenants.withId_closure2(Tenants.groovy:258)
	at grails.gorm.multitenancy.Tenants$CurrentTenant.withTenant(Tenants.groovy:358)
	at grails.gorm.multitenancy.Tenants.withId(Tenants.groovy:236)
	at org.grails.datastore.gorm.services.DefaultTenantService.withCurrent(DefaultTenantService.groovy:71)
	at test.TestServiceSpec.test something somethng(TestServiceSpec.groovy:38)

NPE When Referring To controller In where: Block

The project at https://github.com/jeffbrown/webrequestissue contains the following:

package webrequestissue

class DemoController {

    static final SOME_CONSTANT = 42

    def index(int x, int y) {
        int sum = x + y
        render "$x plus $y is $sum"
    }
}
package webrequestissue

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification
import spock.lang.Unroll

class DemoControllerSpec extends Specification implements ControllerUnitTest<DemoController> {

    @Unroll('#x plus #y should be #sum')
    void "test index"() {
        when:
        params.x = x
        params.y = y
        controller.index()

        then:
        response.text == "$x plus $y is $sum"

        where:
        x  | y | sum
        4  | 5 | 9
        40 | 2 | controller.SOME_CONSTANT
    }
}

Referring to controller in the where: block causes a NullPointerException to be thrown at

webRequest.request.setAttribute(GrailsApplicationAttributes.CONTROLLER, controller)
because webRequest has not yet been initialized. I think it is normally initialized by WebSetupInterceptor at .

InterceptorUnit test does not register actionName

With an interceptor like this:

class ActionNameInterceptor {
    boolean before() {
        println "$controllerName $actionName $params"
        if (actionName) {
            request.setAttribute('actionNameSet', 'action name set')
        }
        return true
    }
}

When running, the actionName is set, but when running tests, the actionName is not set.

See https://github.com/sbglasius/grailsInterceptorBugs interceptorbug.ActionNameInterceptorSpec#Test interceptor actionName should be set to default index and interceptorbug.ActionNameInterceptorSpec#Test interceptor actionName should be set to specific name for tests

Execute samples in test project - ApplicationEventMulticaster not initialized error

The outstanding issue is that when i create an app with create-app, and then do the examples in the doc, all the tests pass but i am getting a exception. Looks like a spring boot lifecyle exception. Note it does not occur in the demo code.

java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.web.context.support.GenericWebApplicationContext@6e9319f: startup date [Mon May 01 11:52:04 CDT 2017]; root of context hierarchy at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:404) at org.springframework.context.support.ApplicationListenerDetector.postProcessBeforeDestruction(ApplicationListenerDetector.java:97) at org.s

mockDataService throws NoSuchMethodError

trying to write a ServiceUnitTest and mock a data service that the service under test is using, i get a NoSuchMethodError:

java.lang.NoSuchMethodError: org.grails.datastore.mapping.core.AbstractDatastore.getService(Ljava/lang/Class;)Lorg/grails/datastore/mapping/services/Service;
	at grails.testing.gorm.DataTest$Trait$Helper.mockDataService(DataTest.groovy:96)
	at myapp.DummyServiceSpec.setupSpec(DummyServiceSpec.groovy:11)

but looking at the code (i.e. the AbstractDatastore.getService method signature), i cannot figure out whats wrong.

sample app will be referenced in a minute.

ServiceUnitTest does not recognise Data Services as Services

For the next domain name:

package demo

class Book {

    String name

    static constraints = {
    }
}

and service:

package demo

import grails.gorm.services.Service
import groovy.transform.CompileStatic

@CompileStatic
@Service(Book)
abstract class BookService {
    abstract List<Book> findAll()
}

The next test:

package demo

import grails.testing.gorm.DataTest
import grails.testing.services.ServiceUnitTest
import spock.lang.Specification

class BookServiceSpec extends Specification implements ServiceUnitTest<BookService>, DataTest {

    def setup() {
        mockDomain(Book)
    }

    void "test there are not book"() {
        expect:
        service.findAll().size() == 0
    }
}

throws the error Cannot add Service class [class demo.BookService]. It is not a Service!

    org.spockframework.runtime.ConditionFailedWithExceptionError at BookServiceSpec.groovy:19
        Caused by: org.grails.core.exceptions.GrailsConfigurationException at BookServiceSpec.groovy:19

Condition failed with Exception:

service.findAll().size() == 0
|
org.grails.core.exceptions.GrailsConfigurationException: Cannot add Service class [class demo.BookService]. It is not a Service!

Condition failed with Exception:

service.findAll().size() == 0
|
org.grails.core.exceptions.GrailsConfigurationException: Cannot add Service class [class demo.BookService]. It is not a Service!

	at demo.BookServiceSpec.test there are not book(BookServiceSpec.groovy:19)
Caused by: org.grails.core.exceptions.GrailsConfigurationException: Cannot add Service class [class demo.BookService]. It is not a Service!
	at grails.core.DefaultGrailsApplication.addArtefact(DefaultGrailsApplication.java:855)
	at grails.core.DefaultGrailsApplication.addArtefact(DefaultGrailsApplication.java:517)
	at grails.testing.services.ServiceUnitTest$Trait$Helper.mockArtefact(ServiceUnitTest.groovy:37)
	at org.grails.testing.ParameterizedGrailsUnitTest$Trait$Helper.getArtefactInstance(ParameterizedGrailsUnitTest.groovy:48)
	at grails.testing.services.ServiceUnitTest$Trait$Helper.getService(ServiceUnitTest.groovy:51)
	... 1 more

GrailsUnitTest.defineBeans(new PluginClass()) does not set grailsApplication /applicationContext?

I have a custom TagLib that makes use of the asset-pipeline-grails (version 3.0.6) AssetsTagLib to display images. It calls asset.image() to output an image tag when it renders.

In order to test this, I have a CustomTagLibSpec that implements TagLibUnitTest, and in the setup method I was expecting to be able to do the following to bootstrap and mock the the relevant asset dependencies:

setup() {`
  defineBeans(new AssetPipelineGrailsPlugin())
  mockTagLib(AssetsTagLib)
  mockTagLib(AssetMethodTagLib)
}

On running the unit test though, I get a failure because grailsApplication is used in the AssetPipelineGrailsPlugin.doWithSpring Closure, and that is not set.

If I change my unit test code to

setup() {`
  def assetPlugin = new AssetPipelineGrailsPlugin()
  assetPlugin.applicationContext = applicationContext
  assetPlugin.grailsApplicatin = grailsApplication
  defineBeans(assetPlugin)
  mockTagLib(AssetsTagLib)
  mockTagLib(AssetMethodTagLib)
}

Then my unit test works.

Given that all plugins implement Plugin, and therefore ApplicationContextAware, and GrailsApplicationAware, can the defineBeans(Object plugin) method in GrailsUnitTest be changed to set the grailsApplication and applicationContext from the unit test to avoid having to do it manually please ?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/docs.yml
  • actions/checkout v4
  • actions/setup-java v4
  • actions/checkout v4
  • gradle/gradle-build-action v3
  • grails/github-pages-deploy-action v2
.github/workflows/gradle.yml
  • actions/checkout v4@8ade135a41bc03ea155e62e844d188df1ea18608
  • actions/setup-java v4
  • gradle/gradle-build-action v3
  • gradle/gradle-build-action v3
  • scacap/action-surefire-report v1
  • gradle/gradle-build-action v3
  • gradle/gradle-build-action v3
.github/workflows/groovy-joint-workflow.yml
  • actions/setup-java v4
  • actions/cache v4
  • gradle/gradle-build-action v3
  • actions/checkout v4
  • actions/setup-java v4
  • actions/cache v4
  • gradle/gradle-build-action v3
.github/workflows/release-notes.yml
  • actions/checkout v4
  • release-drafter/release-drafter v6
  • ncipollo/release-action v1
.github/workflows/release.yml
  • actions/checkout v4
  • actions/setup-java v4
  • gradle/gradle-build-action v3
  • actions/upload-artifact v4
  • gradle/gradle-build-action v3
  • actions/checkout v4
  • actions/setup-java v4
  • actions/checkout v4
  • gradle/gradle-build-action v3
  • actions/setup-java v4
  • actions/checkout v4
  • gradle/gradle-build-action v3
  • grails/github-pages-deploy-action v2
.github/workflows/retry-release.yml
  • actions/checkout v4@8ade135a41bc03ea155e62e844d188df1ea18608
  • actions/setup-java v4
  • gradle/gradle-build-action v3
  • gradle/gradle-build-action v3
gradle
gradle.properties
  • org.grails:grails-gradle-plugin 6.1.2
  • org.grails.plugins:views-gradle 3.2.3
  • com.github.javaparser:javaparser-core 3.25.10
  • javax.servlet:javax.servlet-api 4.0.1
  • org.codehaus.groovy:groovy-test-junit5 3.0.21
  • org.junit.jupiter:junit-jupiter-api 5.10.2
  • org.junit.platform:junit-platform-runner 1.10.2
  • org.junit.jupiter:junit-jupiter-engine 5.10.2
  • org.grails:grails-plugin-domain-class 6.2.0
  • org.grails:grails-datastore-gorm-test 8.1.2
  • org.springframework:spring-test 5.3.33
  • org.grails:grails-plugin-codecs 6.2.0
  • org.grails.plugins:async 5.0.2
  • org.grails:grails-datastore-gorm 8.1.2
  • org.grails:grails-test 6.2.0
  • org.springframework.boot:spring-boot-test 2.7.18
  • org.spockframework:spock-spring 2.1-groovy-3.0
  • org.spockframework:spock-core 2.1-groovy-3.0
  • org.grails.plugins:gsp 6.2.1
  • org.grails:grails-plugin-rest 6.2.0
  • org.grails:grails-plugin-interceptors 6.2.0
  • org.javassist:javassist 3.30.2-GA
settings.gradle
  • com.gradle.enterprise 3.16.2
  • com.gradle.common-custom-user-data-gradle-plugin 2.0
build.gradle
  • io.github.gradle-nexus:publish-plugin 2.0.0
  • org.asciidoctor:asciidoctor-gradle-jvm 4.0.2
grails-gorm-testing-support/build.gradle
grails-testing-support/build.gradle
grails-web-testing-support/build.gradle
gradle-wrapper
gradle/wrapper/gradle-wrapper.properties
  • gradle 7.6.4

  • Check this box to trigger a request for Renovate to run again on this repository

Interceptor tests do not correctly register Interceptor in applicationContext

When writing an Interceptor test, the first test does not actually call the before method in the interceptor at all even if you have a matchAll() in the constructor.

All subsequent tests after the first appear to work fine. It's only the first one that doesn't work. It seems that the bean isn't correctly registered in the application context and the call to: applicationContext.getBeansOfType(Interceptor).values() as Interceptor[] in the mockInterceptor method of InterceptorUnitTest returns an empty list.

I've attached a test project showing the behavior.
InterceptorTestBug.zip

NPE on nested service injection

Hello, I have troubles running tests for a controller similar to this one, observe that TokenService is injected in BackofficeController and NotificationService.

class BackofficeController {

    // TokenService is used by this controller on other methods not shown here
    TokenService tokenService
    NotificationService notificationService

    def index() { }
    
    def sendInvitationConfirm() {
        List<Token> tokenList = Token.findAllByEnabledAndSent(true, false)

        tokenList.each {Token token ->
            notificationService.sendInvitation(token)
        }

        redirect(action:'index')
    }
}
class NotificationService {

    MailService mailService
    TokenService tokenService

     void send(String emailTo, String subjectLine, String layout, Map model = [:]) {
        mailService.sendMail {
            ...
        }
    }

    void sendInvitation(Token token) {
        send(token.email, INVITATION_SUBJECT, 'invitation', [token:token.token])
        token.sent = true
        tokenService.save(token) // <-- Problematic line
    }
}

When running the following test I get a Null Pointer Exception on the "problematic line" of NotificationService.

class BackofficeControllerSpec extends Specification 
        implements ControllerUnitTest<BackofficeController>, DataTest {

    Closure doWithSpring() {{ ->
        tokenService(TokenService)
        notificationService(NotificationService)
    }}

    def setup() {
        mockDomain Token
        controller.notificationService.mailService = Mock(MailService)
    }

    void "Problematic Test"() {
        setup: "Set request method"
            request.method = 'POST'
        and: "Create valid token"
            new Token(email:'[email protected]', token:'A' * 32).save(flush:true)

        when: "Calling the action"
            controller.sendInvitationConfirm()

        then: "Token is updated"
            Token.first().sent
        and: "User is redirected"
            response.redirectedUrl == '/backoffice/index'
    }

java.lang.NullPointerException: Cannot invoke method save() on null object

It is my understanding that by defining the beans in doWithSrping, the injections of TokenService should succeed. However, it seems the injection of BackofficeController.tokenService is successful (tested for other methods of BackofficeController) but the injection for NotificationService.tokenService is not.

The only way I've been able to fix my test is adding the following line to setup in the test

controller.notificationService.tokenService = new TokenService()

This project is running on Grails 3.3.2 with the following (default) gradle configuration:

dependencies {
    testCompile "org.grails:grails-gorm-testing-support"
    testCompile "org.grails:grails-web-testing-support"
}

Am I missing something about service injection?

Reverse URL mapping test fails if mapping includes an http method

Overview: If a URL mapping is prefixed with an HTTP method, e.g., get "/my/mapping", then tests using assertReverseUrlMapping or verifyReverseUrlMapping will not be able to generate the correct URL, resulting in failure of the tests.

Example UrlMappings.groovy (assuming a TestController with an index action exists):

class UrlMappings {
    static mappings = {
        get "/custom/mapping"(controller: 'test', action: 'index')
    }
}

Example unit test/s:

class UrlMappingsSpec  extends Specification implements UrlMappingsUnitTest<UrlMappings> {

    void setup() {
        mockController(TestController)
    }

    void "test forward"() {
        expect: "calls to /custom/mapping to succeed" // <-- passes
        verifyForwardUrlMapping("/custom/mapping", controller: 'test', action: 'index')
    }

    void "test reverse"() {
        expect: "calls to /custom/mapping to succeed" // <-- fails
        verifyReverseUrlMapping("/custom/mapping", controller: 'test', action: 'index')
    }

    void "test both"() {
        expect: "calls to /custom/mapping to succeed" //< -- fails (due to reverse failure)
        verifyUrlMapping("/custom/mapping", controller: 'test', action: 'index')
    }
}

The "test forward" test will pass, the other two will fail. Debugging indicates that the URL returned from UrlCreator.createRelativeURL is test/index (apparently falling back to the default URL mapping with controller name/action name).

Sample project here. Run grails test-app to execute the unit tests in UrlMappingsSpec.

JSON converters not working in ServiceUnitTest

When trying to test a grails service which uses JSON converter throws error.

Exception message is : org.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: java.util.LinkedHashMap

General concept and understanding questions by Nirav

  • in general what is the purpose of the plugin - what i gather is its simple and more efficient way so developers dont have to import annotation like @mock and @testfor
  • in DomainUnitTest, we dont have to mock the domain class. However, in the usage of DataTest we have to use mockDomain (as it was used in 2.x). Why would we go this route.
  • with ServiceUnitTest, what is the difference between using it vs @testfor. is it essentially the same or does it have other traits to use.
  • is doWithSpring in unit test feature contain in the grails-testing-support jar? i thought it was already present before
  • I am not familiar with how the grails scripts run and operate such as create-controller and create-domain-class. Are they scripts in the installation, or have they changed? Where are these checked in and how do we add to development.

Integration test performance degradation compared to grails-test-mixin-plugin

After upgrading an app from Grails 3.2.x to 3.3.x I noticed that integration tests take a lot longer to run.

The old test plugin has a dependency on spring-boot-starter-test which includes mockito-core. Since the new testing framework does not have that dependency, mockito isn't included and it seems as though that is the source of the slowdown. Honestly I have no idea why including mockito-core would affect integration tests, but it does.

To illustrate the difference in performance, an empty Grails 3.3 app runs the following integration test roughly 3x faster if mockito-core is included as a dependency:

@Unroll
void "this test runs faster with mockito"() {
    expect:
    1

    where:
    a << Arrays.asList(new Integer[100]) // run test 100 times
}

Here's a sample project: https://github.com/dpcasady/integration-test-perf

The sample project has a testCompile dependency on mockito-core that is commented out. Run the integration tests to get a sense of the execution time, then uncomment the mockito dependency and run the tests again.

I'm not sure if the new testing framework should include mockito by default, I just thought such a big difference in test execution time should be noted.

No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example.zip that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Add following application.yml
grails:
    gorm:
        multiTenancy:
                mode: DATABASE
                tenantResolverClass: org.grails.datastore.mapping.multitenancy.web.SessionTenantResolver
  1. Create a Domain file (doesn't matter if doesn't have fields
class Book implements MultiTenant<Book> {
    String title
}
  1. Create specification for spock
class BookSpec extends Specification implements DomainUnitTest<Book> {

    void "test something"() {
        expect:"fix me"
            true == true
    }
}

  1. Run the test and you get the stack trace
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.grails.beans.ConstraintsEvaluator': Cannot resolve reference to bean 'grailsDomainClassMappingContext' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grailsDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.datastore.mapping.simple.SimpleMapDatastore]: Constructor threw exception; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]

	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:648)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:145)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
	at org.grails.testing.GrailsUnitTest$Trait$Helper.defineBeans(GrailsUnitTest.groovy:100)
	at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.setupDataTestBeans(DataTestSetupSpecInterceptor.groovy:48)
	at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.configureDataTest(DataTestSetupSpecInterceptor.groovy:75)
	at org.grails.testing.gorm.spock.DataTestSetupSpecInterceptor.intercept(DataTestSetupSpecInterceptor.groovy:41)
	at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:87)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grailsDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.datastore.mapping.simple.SimpleMapDatastore]: Constructor threw exception; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:279)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1193)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1095)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
	... 22 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.datastore.mapping.simple.SimpleMapDatastore]: Constructor threw exception; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122)
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:271)
	... 40 more
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]
	at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:324)
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:206)
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187)
	at org.springframework.core.env.AbstractPropertyResolver.convertValueIfNecessary(AbstractPropertyResolver.java:266)
	at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:87)
	at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:66)
	at org.springframework.core.env.AbstractPropertyResolver.getProperty(AbstractPropertyResolver.java:169)
	at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:542)
	at org.grails.datastore.mapping.config.ConfigurationBuilder.buildRecurse(ConfigurationBuilder.groovy:290)
	at org.grails.datastore.mapping.config.ConfigurationBuilder.buildRecurse(ConfigurationBuilder.groovy:235)
	at org.grails.datastore.mapping.config.ConfigurationBuilder.buildInternal(ConfigurationBuilder.groovy:111)
	at org.grails.datastore.mapping.config.ConfigurationBuilder.build(ConfigurationBuilder.groovy:92)
	at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.create(AbstractConnectionSourceFactory.java:45)
	at org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer.create(ConnectionSourcesInitializer.groovy:24)
	at org.grails.datastore.mapping.simple.SimpleMapDatastore.<init>(SimpleMapDatastore.java:117)
	at org.grails.datastore.mapping.simple.SimpleMapDatastore.<init>(SimpleMapDatastore.java:178)
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)

Expected Behaviour

I expected test without errors

Actual Behaviour

I get BeanCreationException error

Environment Information

  • Operating System: macOs
  • Grails Version: 3.3.2
  • JDK Version: 8u111

inconsistent query results after updating domain instances in a service (DataTest/ServiceUnitTest)

given a unit test (DataTest, ServiceUnitTest), after updating domain objects (i.e. persistent entity instances) in a @Transactional service, subsequent queries produce inconsistent/wrong results with instances still having the old/pre-update values.

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. run sample app tests (DummySpec)
  2. see test failures

Expected Behaviour

  • sample app tests should pass

Actual Behaviour

Condition failed with Exception:

dummyWithNewNameFromService.name == "updatedDummyExplicit"
|                           |
null                        java.lang.NullPointerException: Cannot get property 'name' on null object


	at myapp.DummySpec.test find after update with explicit flush from service_closure1(DummySpec.groovy:30)
	at myapp.DummySpec.test find after update with explicit flush from service_closure1(DummySpec.groovy)
	at groovy.lang.Closure.call(Closure.java:418)
	at spock.lang.Specification.verifyAll(Specification.java:223)
	at myapp.DummySpec.test find after update with explicit flush from service(DummySpec.groovy:25)
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object
	... 5 more


Condition not satisfied:

!dummyWithOldName
||
|myapp.Dummy : 1
false


	at myapp.DummySpec.test find after update with implicit flush from service_closure2(DummySpec.groovy:47)
	at myapp.DummySpec.test find after update with implicit flush from service_closure2(DummySpec.groovy)
	at groovy.lang.Closure.call(Closure.java:418)
	at spock.lang.Specification.verifyAll(Specification.java:223)
	at myapp.DummySpec.test find after update with implicit flush from service(DummySpec.groovy:45)


Condition failed with Exception:

dummyWithNewName.name == "updatedDummyImplicit"
|                |
null             java.lang.NullPointerException: Cannot get property 'name' on null object


	at myapp.DummySpec.test find after update with implicit flush from service_closure2(DummySpec.groovy:48)
	at myapp.DummySpec.test find after update with implicit flush from service_closure2(DummySpec.groovy)
	at groovy.lang.Closure.call(Closure.java:418)
	at spock.lang.Specification.verifyAll(Specification.java:223)
	at myapp.DummySpec.test find after update with implicit flush from service(DummySpec.groovy:45)
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object
	... 5 more


Condition failed with Exception:

dummyWithNewNameFromService.name == "updatedDummyImplicit"
|                           |
null                        java.lang.NullPointerException: Cannot get property 'name' on null object


	at myapp.DummySpec.test find after update with implicit flush from service_closure2(DummySpec.groovy:50)
	at myapp.DummySpec.test find after update with implicit flush from service_closure2(DummySpec.groovy)
	at groovy.lang.Closure.call(Closure.java:418)
	at spock.lang.Specification.verifyAll(Specification.java:223)
	at myapp.DummySpec.test find after update with implicit flush from service(DummySpec.groovy:45)
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object
	... 5 more

Environment Information

  • Operating System: win x64
  • Grails Version: 3.3.5
  • JDK Version: oracle 8u151
  • Container Version (If Applicable): n/a

Example Application

a simplified sample app will be referenced in a minute, see DummySpec (and the different failues for each of the two test methods).

if there is anything i can do to help/speed-up fixing this, just gimme a ping.

Issue Testing Non Public Controller Methods

The repo at https://github.com/jeffbrown/privatemethodissue contains the following contains the following:

package privatemethodissue

class DemoController {

    DemoService demoService

    def index() {}

    String somePublicMethod() {
        demoService.someString
    }

    protected String someProtectedMethod() {
        demoService.someString
    }

    private String somePrivateMethod() {
        demoService.someString
    }
}
package privatemethodissue

class DemoService {

    String getSomeString() {
        'Some String'
    }
}

The following test will fail for the non-public methods because the service instance is null in the controller methods. The public method passes.

package privatemethodissue

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class DemoControllerSpec extends Specification implements ControllerUnitTest<DemoController> {

    def setup() {
        controller.demoService = Mock(DemoService) {
            getSomeString() >> 'Some Mock String'
        }
    }

    void "test using a public helper method"() {
        expect:
        controller.somePublicMethod() == 'Some Mock String'
    }

    void "test using a protected helper method"() {
        expect:
        controller.someProtectedMethod() == 'Some Mock String'
    }

    void "test using a private helper method"() {
        expect:
        controller.somePrivateMethod() == 'Some Mock String'
    }
}

Disabling the controller proxy resolves the issue. The following tests pass:

package privatemethodissue

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class DemoControllerWithNoProxySpec extends Specification implements ControllerUnitTest<DemoController> {

    def setup() {
        controller.demoService = Mock(DemoService) {
            getSomeString() >> 'Some Mock String'
        }
    }

    void "test using a public helper method"() {
        expect:
        controller.somePublicMethod() == 'Some Mock String'
    }

    void "test using a protected helper method"() {
        expect:
        controller.someProtectedMethod() == 'Some Mock String'
    }

    void "test using a private helper method"() {
        expect:
        controller.somePrivateMethod() == 'Some Mock String'
    }


    boolean disableControllerProxy() {
        true
    }
}

I don't think disableControllerProxy() is mentioned anywhere in the docs.

HibernateSpec and DataTest are incompatible

HibernateSpec and DataTest are incompatible as they both create two different kind of datastore. As a results, it is impossible to have a unit test extending HibernateSpec and that test code using the mapping context.

It also results in some features that are not working as expected. For example the @transactional annotation on unit test doesnt work anymore if you implement DataTest, since GORM doesn't know which datastore to choose.

You can see a sample project with those cases here : https://github.com/anthonyMoreira/bug-hibernatespec

The integration between HibernateSpec and DomainUnitTest/ServiceUnitTest/DataTest should be transparent for the developpers and/or well documented.

InterceptorUnitTest does not set params

With an interceptor like this:

class ActionNameInterceptor {
    boolean before() {
        println "$controllerName $actionName $params"
        if(params.test == 'is set') {
            request.setAttribute('paramSet', 'param set')
        }
        return true
    }
}

When running, the params is set, but when running tests, the params is not set.

See https://github.com/sbglasius/grailsInterceptorBugs interceptorbug.ActionNameInterceptorSpec#Test interceptor params should be set

Grails 3.3.10: Testing shared constrints on command object fails

Hi

This is an update to the #54 (I will close that one, the old one was using deprecated classes)

I am using grails 3.3.10. I think I found a bug when I try to test shared constraints in the command objects.

The constraint is not available to the command object and it throws an exception.

Using the shared constraints in a domain works well as expected.

Steps to Reproduce

The domain

class User {
	String firstName
	static constraints = {
		firstName shared: 'nonNullableString'
	}
	static mapping = {
		table '`user`'
	}
}

The command object inside a controller. This is my example

class AdminUserController {
	def save(UserCommand command) {
		if (command.hasErrors()) {
			render view: 'create', model: [command: command]
			return
		}
		new User(firstName: command.firstName).save()
		flash.success = message(code: 'default.created.message')
		redirect action: 'list'
	}
}

class UserCommand implements Validateable{
	String firstName

	static constraints = {
		firstName shared: 'nonNullableString'
	}
}

Than add the constraints in the application.groovy

grails.gorm.default.constraints = {
	nonNullableString(blank: false, maxSize: 255)
}

And then test

void testUserCommand() {
		when:
		UserCommand command = new UserCommand()

		then:
        	!command.validate()
		command.errors['firstName'].code == 'nullable'
       }

Expected Behaviour

I expect the test to run

Actual Behaviour

The command object does not have the constraints during the test. I throws this exception

!command.validate()
| |
| grails.gorm.validation.exceptions.ValidationConfigurationException: Property [commandtests.UserCommand.firstName] references shared constraint [nonNullableString:null], which doesn't exist!
commandtests.UserCommand@1142f026

Environment Information

MacOS 10.14.4
Grails 3.3.10
JDK 1.8

Example Application

I created a simple project with the problem. It is available in this repository
https://github.com/almejo/commandtest

Documentation for HibernateSpec is missing

I couldnt find documentation for HibernateSpec anywhere other then some examples in grails guides, if i am not missing some thing. I think it used to be available in grails reference docs earlier.

Please have HibernateSpec documented, either in gorm docs, or in grails testing docs.

Unable to test domain using not default datasource

i initially created issue but in wrong place grails/grails-core#10888

while doing test i have error :

org.grails.datastore.mapping.core.exceptions.ConfigurationException: Invalid connection [myDataSource] configured for class [class joe.Test]

I spent already days on this, cannot find correct solution.
One idea was to overwrite method getDatastore bdbogjoe/unit-test-multiple-datasource#2 but in some case does not work and don't think it is correct way to do this.

Do you have any idea how to fix this ? Was working fine in grails 3.1.x

Incorrect validation when using deepValidate:false

For unit tests, using validate(deepValidate:false) on already persisted domains, sometimes return an incorrect result.

For example, for the following domain

class Example {

    Boolean alpha
    Boolean beta
    String sigma

    static constraints = {
        isValid notEqual:false
        sigma   notEqual:'bad'
    }

    Boolean getIsValid() {
        alpha || beta
    }
}

These tests fail as unit tests (because validate returns true) but pass as integration tests

    void "Test isValid for saved instance"() {
        given:
            new Example(alpha:true, beta:true, sigma:'good').save(flush:true)
            assert Example.count() == 1

        when:
            Example example = Example.first()
            example.alpha = false
            example.beta = false

        then:
            !example.validate(deepValidate:false)
            example.errors.getFieldError('isValid').code == 'notEqual'
    }

    void "Test sigma for saved instance"() {
        given:
            new Example(alpha:true, beta:true, sigma:'good').save(flush:true)
            assert Example.count() == 1

        when:
            Example example = Example.first()
            example.sigma = 'bad'

        then:
            !example.validate(deepValidate:false)
            example.errors.getFieldError('sigma').code == 'notEqual'
    }

You will find the relevant tests in the Grails 3.3.8 sample project, in the files ExampleSpec.groovy and ExampleIntegrationSpec.groovy
strange_validation.zip

Thanks in advance

In GORM for MongoDB, some features won't work unless you use MongoSpec

I'm not sure whether this is an actual issue we can improve, or simply something we can clarify in the documentation.

The issue is that with a standard mocking from DomainUnitTest or DataTest, some GORM features are not working, like the default sort order defined in mapping{}. I think the reason why is because a MongoDatastore is required instead of SimpleMapDatastore. But maybe the reason is different.

In order for such GORM form MongoDB features to work, one needs to extend from grails.test.mongodb.MongoSpec, and forget about DomainUnitTest or DataTest mocking.

Grails 3.3.10: Testing shared constrints on command object fails on migration from grails 2 to grails 3

Hi

I am migrating a 2.5.4 project to grails 3.3.10 and I use the compatibility layer to use my old test. I think I found a bug when I try to test shared constraints in the command objects.
The constraint is not available to the command object and it throws an exception.

Using the shared constraints in a domain works well as expected.

I also tried to use the new way of writing test files, with the ControllerUnitTest but the result is the same

Steps to Reproduce

Create a command object inside a controller. This is my example

class AdminUserController {
	def save(UserCommand command) {
		if (command.hasErrors()) {
			render view: 'create', model: [command: command]
			return
		}
		new User(firstName: command.firstName).save()
		flash.success = message(code: 'default.created.message')
		redirect action: 'list'
	}
}

class UserCommand implements Validateable{
	String firstName

	static constraints = {
		firstName shared: 'nonNullableString'
	}
}

Than add the constraints in the application.groovy


grails.gorm.default.constraints = {
	nonNullableString(blank: false, maxSize: 255)
}

And then test

@TestFor(AdminUserController)
@Mock([User])
class AdminUserControllerSpec extends Specification {

	void testUserCommand() {
		when:
		UserCommand command = new UserCommand()

		then:
		!command.validate()
		command.errors['firstName'].code == 'nullable'
       }

Expected Behaviour

I expect the test to run as in grails 2.5.4

Actual Behaviour

The command object does not have the constraints during the test. I throws this exception

!command.validate()
| |
| grails.gorm.validation.exceptions.ValidationConfigurationException: Property [commandtests.UserCommand.firstName] references shared constraint [nonNullableString:null], which doesn't exist!
commandtests.UserCommand@1142f026

Environment Information

  • MacOS 10.14.4
  • Grails 3.3.10
  • JDK 1.8

Example Application

I created a simple project with the problem. It is available in this repository
https://github.com/almejo/commandtest

Exception testing a controller or a service with a service injected with autowired

grails version: 3.3.11

Given a controller unit test that have a service injected with an autowired annotation It throws an exception NoSuchBeanDefinitionException.

I've reproduced the issue on a repository. It's been created with grails version 3.3.11, an item class domain and some code generated with scaffolding. I've left the test working and made the change on ItemController injecting the service with autowired on the last commit.

Git Repository with an example: https://github.com/xavier-gallofre/grails-test-autowired-issue

es.xagani.grailsTestAutowired.ItemControllerSpec > Test the index action returns the correct model FAILED
    org.springframework.beans.factory.UnsatisfiedDependencyException at ItemControllerSpec.groovy:18
        Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException at ItemControllerSpec.groovy:18

@Rollback annotation doesn't work in integration test

I'm writing an integration test to test my "JSON" (in the real app it is) API.

I have a simple domain class User { String email } and a controller that checks for duplicate emails before creation. I have two integration tests that both do the same thing, make a GET request and check response.status == 201 and User.count == 1.

Currently, I have these two tests in separate files, UserSpec and UserSpecAgain. You could put both tests in the same class and it will cause the same issue. For me, UserSpecAgain runs first and it passes fine, and then UserSpec runs, but the domain wasn't cleared so that test fails due to a duplicate email.

I have the @Rollback annotation on both my test specs, but it doesn't seem anything gets rolled back.

These integration tests never worked right for me (even on the old framework). I thought they were just like unit tests, but without the need to mock anything, etc. Maybe I was wrong on my assumption. Functional tests seem to lack good documentation so I'm just piecing stuff together.

testing-demo.zip

Spock tests are executing @BeforeEach but not @AfterEach

Some of the extensions provided in this library are causing specs to execute methods annotated with JUnit5's @BeforeEach but not @AfterEach.

I'm not sure if this library is trying to emulate the @BeforeEach or if it's just something leftover, but the current behavior is not super useful.

Critically, the ordering of the calls is different than in Grails 4.0, i.e it used to be:

beforeEach
setup
test method
cleanup
afterEach

Now the ordering is:

setup
beforeEach
test method
cleanup

This makes it difficult to use @BeforeEach in a trait or base class as usually you will want that to be called first (which it used to be). Also, Spock makes it difficult since traits can't use setup() if the test class also has a setup method.

IMO, this library should implement an extension that creates compatibility with Before* and After* annotations while keeping the test order consistent with pre-5.0 behavior (and what would be considered the sensical ordering)

package test

import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import spock.lang.Specification

class TestAnnotationSpec extends Specification {

    def "test method 1"() {
        when:
        println "test method 1"

        then:
        true
    }

    @BeforeEach
    void beforeEach() {
        println "beforeEach"
    }

    @AfterEach
    void afterEach() {
        println "afterEach"
    }

    void setup() {
        println "setup"
    }

    void cleanup() {
        println "cleanup"
    }
}

Add support to GrailsApplicationBuilder(or GrailsUnitTest) to conditionally load external beans (from resources.groovy)

Grails team,

I'm currently writing unit test where I'm verifying a Camunda BPM process definition is correctly configured. The application defines multiple beans for different purposes including the multiple ones you need to make use of Camunda API declare in resources.groovy

A typical application resources.groovywould look like this:

beans = {
//Other bean deinition
 userPasswordEncoderListener(UserPasswordEncoderListener)
 authenticationEntryPoint(Http401AuthenticationEntryPoint, 'Bearer')
 logoutSuccessHandler(HttpStatusReturningLogoutSuccessHandler, HttpStatus.NO_CONTENT)
    


    //Camunda spring bean configuration
    identityProviderSessionFactory(SpringSecurityCorePluginSessionFactory)
    processEngineConfiguration(SpringProcessEngineConfiguration){
        processEngineName = "camunda-engine-${appName}-${Environment.currentEnvironment}"
        dataSource = ref("dataSource")
        databaseType = databaseUsing
        databaseSchemaUpdate = camundaSchemaStrategy
        transactionManager = ref("transactionManager")
        history = ProcessEngineConfiguration.HISTORY_DEFAULT
        jobExecutorActivate = jobExecutorEnabled
        customSessionFactories = [ref("identityProviderSessionFactory")]
    }

    processEngine(ProcessEngineFactoryBean){ bean ->
        processEngineConfiguration = ref("processEngineConfiguration")
    }

    runtimeService(processEngine: "getRuntimeService")
    taskService(processEngine: "getTaskService")
    identityService(processEngine: "getIdentityService")
    historyService(processEngine: "getHistoryService")
    formService(processEngine: "getFormService")
    managementService(processEngine: "getManagementService")
    filterService(processEngine: "getFilterService")
    externalTaskService(processEngine: "getExternalTaskService")
    caseService(processEngine: "getCaseService")
    decisionService(processEngine: "getDecisionService")
    repositoryService(processEngine: "getRepositoryService")
}

As you may see Camunda, requires a considerable amount of beans/code. Although you can create separated spring bean definition(doWithSpring(), xml, @Config ) for your unit test to declare only beans necessary for your test spec, it is better to use the same source to run the application(resources.groovy) and your test meeting with the DRY principle but the problem is that loadExternalBeanDefinion() loads all beans when for the purpose of testing, you only need to load a subset of what it is declared(in my case only Camunda Beans).

Is there any way to enhance GrailsUnitTest trait and/or GrailsApplicationBuilder class in order to enable a bean inclusion and/or exclusion Setsimilar to the plugin load feature already offered by Grails testing support?

For example:

class ProcessDefinitionSpec extends Specification implements AutowiredTest {
    Closure doWithSpring() {{ ->
        taskListener1(InstanceFactoryBean, Mock(ApprovalTaskListener))
    }}

   boolean loadExternalBeans() {true }
  
   Set<String> excludingBeans(){
        ["userPasswordEncoderListener", "authenticationEntryPoint", "logoutSuccessHandler"]. toSet()
   }

   // ALL TEST BELOW HERE
}

or using an inclusion Set:

class ProcessDefinitionSpec extends Specification implements AutowiredTest {
    Closure doWithSpring() {{ ->
        taskListener1(InstanceFactoryBean, Mock(ApprovalTaskListener))
    }}

   boolean loadExternalBeans() {true }
  
   Set<String> includinglBeans(){
      ["identityProviderSessionFactory", "processEngineConfiguration", "processEngine", "runtimeService", "taskService", "repositoryService"]. toSet()
   }

   // ALL TEST BELOW HERE
}

I hope I explain the use case well!

Saludos
Hugo

V2.2.0.M1, Grails 4.1.0.M1: Integration test not working

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. Create a project: grails create-app blankProject
    The project is created, go to /blankProject

  2. Create a integration test: grails create-integration-test blankIntegrationTest
    As default, this test is created:

void "test something"() {  
        expect:"fix me"
            true == false
    }
  1. Try to run the new test: grails test-app -integration
    The result tells all tests passed. But actually the test was not executed.

  2. To see what really happened, execute the specific test:
    grails test-app BlankIntegrationTestSpec --stacktrace

Expected Behaviour

The test should execute and fail.

Actual Behaviour

The test do not execute, due to the error below:

$ grails test-app BlankIntegrationTestSpec --stacktrace
Picked up JAVA_TOOL_OPTIONS: -Dprism.order=sw -Xms256m  -Xmx2048m -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=25
> Task :integrationTest FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':integrationTest'.
> No tests found for given includes: [BlankIntegrationTestSpec](--tests filter)

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':integrationTest'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:95)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:91)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:119)
        at org.gradle.api.internal.tasks.execution.ResolvePreviousStateExecuter.execute(ResolvePreviousStateExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:93)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:45)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:94)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:67)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:315)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:305)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:101)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:49)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: org.gradle.api.tasks.testing.TestExecutionException: No tests found for given includes: [BlankIntegrationTestSpec](--tests filter)
        at org.gradle.api.internal.tasks.testing.NoMatchingTestsReporter.afterSuite(NoMatchingTestsReporter.java:37)
        at jdk.internal.reflect.GeneratedMethodAccessor168.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy68.afterSuite(Unknown Source)
        at org.gradle.api.internal.tasks.testing.results.TestListenerAdapter.completed(TestListenerAdapter.java:48)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy70.completed(Unknown Source)
        at org.gradle.api.internal.tasks.testing.results.StateTrackingTestResultProcessor.completed(StateTrackingTestResultProcessor.java:96)
        at org.gradle.api.internal.tasks.testing.results.AttachParentTestResultProcessor.completed(AttachParentTestResultProcessor.java:56)
        at org.gradle.api.internal.tasks.testing.processors.TestMainAction.run(TestMainAction.java:60)
        at org.gradle.api.internal.tasks.testing.detection.DefaultTestExecuter.execute(DefaultTestExecuter.java:116)
        at org.gradle.api.internal.tasks.testing.detection.DefaultTestExecuter.execute(DefaultTestExecuter.java:51)
        at org.gradle.api.tasks.testing.AbstractTestTask.executeTests(AbstractTestTask.java:483)
        at org.gradle.api.tasks.testing.Test.executeTests(Test.java:587)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:48)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:41)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:704)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:671)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$2.run(ExecuteActionsTaskExecuter.java:284)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:273)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:258)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$200(ExecuteActionsTaskExecuter.java:67)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:145)
        at org.gradle.internal.execution.impl.steps.ExecuteStep.execute(ExecuteStep.java:49)
        at org.gradle.internal.execution.impl.steps.CancelExecutionStep.execute(CancelExecutionStep.java:34)
        at org.gradle.internal.execution.impl.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:69)
        at org.gradle.internal.execution.impl.steps.TimeoutStep.execute(TimeoutStep.java:49)
        at org.gradle.internal.execution.impl.steps.CatchExceptionStep.execute(CatchExceptionStep.java:33)
        at org.gradle.internal.execution.impl.steps.CreateOutputsStep.execute(CreateOutputsStep.java:50)
        at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:43)
        at org.gradle.internal.execution.impl.steps.SnapshotOutputStep.execute(SnapshotOutputStep.java:29)
        at org.gradle.internal.execution.impl.steps.CacheStep.executeWithoutCache(CacheStep.java:134)
        at org.gradle.internal.execution.impl.steps.CacheStep.lambda$execute$3(CacheStep.java:83)
        at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:82)
        at org.gradle.internal.execution.impl.steps.CacheStep.execute(CacheStep.java:36)
        at org.gradle.internal.execution.impl.steps.PrepareCachingStep.execute(PrepareCachingStep.java:33)
        at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:38)
        at org.gradle.internal.execution.impl.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:23)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:89)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:52)
        at org.gradle.internal.execution.impl.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:36)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:34)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:91)
        ... 32 more


* Get more help at https://help.gradle.org

BUILD FAILED in 1s
9 actionable tasks: 3 executed, 6 up-to-date
| Tests FAILED Test execution failed

Environment Information

  • Operating System: Ubuntu 19
  • Grails Version: 4.1.0.M1
  • grails-testing-support version: 2.2.0.M1
  • JDK Version: openjdk version "11.0.7"
  • Container Version (If Applicable):

Example Application

https://github.com/tessarini/grailsIssueWithSpock

@TestFor(Domain) class exposed domain property, DomainUnitTest does not

You used to be able to do:

@TestFor(Book) 
class BookSpec extends Specification {
    def "validate is not nullable"() {
         when:
         domain.name = null
         def result = domain.validate(['name'])

         then:
         !result
    }
}

DomainUnitTest does not instantiate domain property as old @TestFor annotation did.

Workaround:

class BookSpec extends Specification implements DomainUnitTest<Book> {

    @Subject
    Book domain
    def setup() {
        domain = new Book()
    }

    def "validate is not nullable"() {
         when:
         domain.name = null
         def result = domain.validate(['name'])

         then:
         !result
    }
}

Or a solution could be to implement something like

T getDomain()

as the ControllerUnitTest does:

https://github.com/grails/grails-testing-support/blob/master/grails-web-testing-support/src/main/groovy/grails/testing/web/controllers/ControllerUnitTest.groovy#L82

Controller action returns a Map, but the map's keys are not available in the model?

Steps to reproduce

  1. Create an app with rest-api profile

$ grails --version
| Grails Version: 3.3.0.RC1
| Groovy Version: 2.4.12
| JVM Version: 1.8.0_121
testing_fw_model sdelamo$ grails create-app --profile=rest-api --inplace

The create-app command generates a controller such as:

package testing_fw_model
import grails.core.GrailsApplication
import grails.util.Environment
import grails.plugins.*

class ApplicationController implements PluginManagerAware {

    GrailsApplication grailsApplication
    GrailsPluginManager pluginManager

    def index() {
        [grailsApplication: grailsApplication, pluginManager: pluginManager]
    }
}

The following unit test fails because model keySet is empty.

package testing_fw_model

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class ApplicationControllerSpec extends Specification implements ControllerUnitTest<ApplicationController> {
   def "index returns valid model"() {
       when:
       controller.index()

       then:
       model.keySet().size() == 2
       model.keySet().contains 'grailsApplication'
       model.keySet().contains 'pluginManager'
   }
}

The type grails.testing.gorm.DomainUnitTest$Trait$FieldHelper$1 cannot be resolved. It is indirectly referenced from required .class files

Eclipse 4.7.2
Gradle 4.6 (testCompile 'org.grails:grails-gorm-testing-support:1.1.4')

import grails.testing.gorm.DomainUnitTest
import spock.lang.Specification
import spock.lang.Unroll

class DomainSpec extends Specification implements DomainUnitTest<Domain> {

In-eclipse > Project > Clean (start a build immediately) gives error:
The type grails.testing.gorm.DomainUnitTest$Trait$FieldHelper$1 cannot be resolved. It is indirectly referenced from required .class files

I have checked internals of referenced grails-gorm-testing-support-1.1.4.jar

  • it does not contain grails.testing.gorm.DomainUnitTest$Trait$FieldHelper$1.class

Is it an IDE related issue? If so, any tips on how to get rid of it?

Fails to compile master (urgent)

When trying to compile master, I get the following error:

BUG! exception in phase 'semantic analysis' in source unit '/home/sbglasius/projects/grails3-plugins/grails-testing-support/grails-web-testing-support/src/main/groovy/grails/testing/web/taglib/TagLibUnitTest.groovy' ClassNode#getTypeClass for grails.testing.web.GrailsWebUnitTest is called before the type class is set 

Preventing me from attempting to fix the issues I have reported.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.