Have a @PostConstruct in the service to ensure that the dependencies have been set up. Dependencies are set in resources.groovy. Unit test fails on @PostConstruct asserts. Tried setting up the dependencies manually in setUpSpec to no avail. Even without a @TestFor, ServiceUnitTestMixin kicks in and merrily chokes on @PostConstruct.
Opened a defect GRAILS-11878 which was closed promptly with an advice to use @FreshRuntime and doWithSpring. If they actually bothered to try, they'd have gotten the following error:
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'grails.spring.BeanBuilder$ConfigurableRuntimeBeanReference$WrappedPropertyValue@2cce10bc' with class 'grails.spring.BeanBuilder$ConfigurableRuntimeBeanReference$WrappedPropertyValue' to class 'java.util.Collection'
Service under test:
@Transactional
class MovieRipIndexService {
Collection<String> genres
Collection<String> includes
@PostConstruct
void postConstruct() {
notEmpty(genres as Collection, 'Genres must not be null or empty.')
notEmpty(includes as Collection, 'Includes must not be null or empty.')
}
}
Test:
@FreshRuntime
@TestFor(MovieRipIndexService)
class MovieRipIndexServiceSpec extends Specification {
def doWithSpring = {
serviceHelper(ServiceHelper)
service.genres = serviceHelper.genres
service.includes = serviceHelper.includes
}
}
Spring support in unit tests is rather minimal, and the
ApplicationContextthat's active doesn't really go through any of the lifecycle phases that it would in a running app, or even during initialization of integration tests. You get a lot of functionality mixed into your class when using@TestForand/or@Mock, but it's almost entirely faked out so you can focus on unit testing the class under test.I tried implementing
org.springframework.beans.factory.InitializingBeanjust now and that worked, so you might get further with that.@Transactionalwill also be ignored - the "database" is aConcurrentHashMap, so you wouldn't get far with that anyway.If you need real Spring behavior, use integration tests. Unit tests are fast and convenient but only useful for a fairly limited number of scenarios.