Grails service injection into integration test - grails

I have a very simple Grails Service:
class UserService {
def returnHi() { return "Hi" }
}
I'm trying to get access to the service in an integration test, like this:
def testService() {
UserService userService
assertEquals( "Hi", userService.returnHi() )
}
Why do I get the failure:
java.lang.NullPointerException: Cannot invoke method returnHi() on null object?
Thanks for your time

It's enough to put 'def userService' as your class field instead of putting in inside of the method. In integration tests, beans are injected the same as in controllers, services and other beans.
Do something like:
class MyTests {
def userService
void serviceTest(){
assert userService.returnHi(), 'Hi'
}
}
P.S. Make sure the name of the service is correct and written in camelCase.

Add the following lines to the integration test file:
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
def userService = AH.application.mainContext.userService
as described here: Service is not getting injected into Grails domain class , Grails 2.0.0 and 2.0.3

Related

Grails Dependency Injection from Service

I am trying to injecting my own service elasticsearchService from the following domain class:
class DocumentESO extends ElasticsearchObject{
ElasticsearchService elasticsearchService
def afterInsert() {
elasticsearchService.save(this) // <-- Cannot invoke method save() on null object
}
}
However, it tells me that it Cannot invoke method save() on null object. Here is my service:
#Transactional
class ElasticsearchService {
#Transactional
def save(ElasticsearchObject esObject) {...}
}
Did I misspell something? If I would use ElasticsearchService elasticsearchService = new ElasticsearchService() then it would work, but I don't have the transactional support anymore.
In this answer, robert mentions it needs to initialized, while using meta programming save() for example. Does it mean that I cannot go with dependency injection in this case?
Thus it would be:
def afterInsert() {
ElasticsearchService elasticsearchService = new ElasticsearchService()
elasticsearchService.save(this)
}
??
Service injection in GORM entities is disabled by default since Grails 3.2.8.
You can turn on autowiring in this one particular domain class by adding to DocumentESO:
static mapping = {
autowire true
}
however it's not recommended: https://grails.org/blog/2017-05-09.html

How to inject a mock for a field (using autowired) in a Grails service that is under unit test?

In my current setup i want to unit test a Grails service that has an #autowired dependency and inject a mock for the dependency.
class AcmeService {
#Autowired
FooService fooService // not a Grails service!
}
The FooService is not a Grails service but it is a dynamic implementation from a FeignClient. I am looking for a way to inject a Mock for the FooService service in a UnitTest. What would be the best solution to do this?
I tried setting the dependency in the setup, but then i get a 'Unsatisfied dependency expressed through field fooService'
class AcmeService extends Specification {
FooService mockedFooService = Mock(FooService)
def setup() {
service.fooService = mockedFooService
}
}
you can add the following to your unit test:
def doWithSpring = {
fooService( InstanceFactoryBean, Mock(FooService) )
}

Inject Spring Beans from resources.groovy into integration test for a Grails 3 Service

I am trying to write an integration test for a service that has a spring bean injected into it. The spring bean is defined in resources.groovy. The bean that my service is using does not appear to be getting injected in my integration test, but it gets injected fine when i run grails run-app.
Here is a minimal failing example:
grails-app/conf/spring/resources.groovy
beans = {
myBean(Object){}
}
grails-app/services/MyService.groovy
class MyService {
def myBean
def serviceMethod(){
myBean.class.simpleName
}
}
grails-app/src/integration-test/groovy/MyServiceSpec.groovy
#Integration
class MyServiceSpec extends Specification {
def myService
when:
def myBean = myService.myBean
then:
myBean != null
}
Grails version info:
$ grails -v
| Grails Version: 3.1.9
| Groovy Version: 2.4.7
| JVM Version: 1.8.0_92
Update:
Spring seems to inject other services just fine. If I declare another service inside of MyService, it gets injected.
class MyService {
def myBean
def myOtherService
def serviceMethod(){
myBean.class.simpleName
}
}
I may be late to the party on this one... But, for future readers, try setting grails.gorm.autowire to true in your application.yml
There are a number of peculiar things about your example, e.g.
beans = {
myBean(Object){}
}
I can't imagine why you'd want to create a bean of type Object, but maybe this is a simplification you made for the purposes of the example and the real bean has a different type.
#Integration
class MyServiceSpec extends Specification {
def myService
when:
def myBean = myService.myBean
then:
myBean != null
}
This test boils down to testing whether dependency injection works, which means your testing Spring/Grails rather than your own code. This is not something you should be testing IMO.
Anyhow to fix your problem I think you just need to add an #Autowired annotation
import org.springframework.beans.factory.annotation.*
#Integration
class MyServiceSpec extends Specification {
#Autowired
def myService
when:
def myBean = myService.myBean
then:
myBean != null
}

Integration testing Grails services with injection

I am having problems integration testing my Grails service because the service under test is not being injected in to my test. I have followed the advice from answers to questions else where on Stackoverflow but as yet can not get my service injected. The following class is under /<project_root>/test/integration/com/example:
package com.example
import grails.test.GrailsUnitTestCase
class MyServiceIntegrationTest extends GroovyTestCase {
MyService service;
public void testService() {
assert service != null
}
}
I have tried executing both from the command-line (grails test-app) and from within IDEA both result in the same failure, namely service is null
This is Grails 1.3.6
Any suggestions on how to get my integration test working please?
Autowiring works the same way in integration tests as in other parts of the framework, so you need to make sure the property is named like the service except with the appropriate unCamelCase.
class MyServiceIntegrationTest extends GroovyTestCase {
def myService
}
Assuming your service is an object named MyService.

Inject grails application configuration into service

I'm creating a grails service that will interact with a 3rd party REST API via a Java library. The Java library requires credentials for the REST API by means of a url, username and password.
I'd like to store these credentials in configuration/Config.groovy, make them available to a service and ensure that credentials are available to the service before it requires them.
I appreciate that grailsApplication.config is available to controllers and that through a method of a service the relevant config values can be provided to the service, such as this:
package example
class ExampleController {
def exampleService
def index = { }
def process = {
exampleService.setCredentials(grailsApplication.config.apiCredentials)
exampleService.relevantMethod()
}
}
package example
import com.example.ExampleApiClient;
class ExampleService {
def credentials
def setCredentials(credentials) {
this.credentials = credentials
}
def relevantMethod() {
def client = new ExampleApiClient(
credentials.baseUrl,
credentials.username,
credentials.password
)
return client.action();
}
}
I feel this approach is slightly flawed as it depends on a controller calling setCredentials(). Having the credentials made available to the service automagically would be more robust.
Is either of these two options viable (I currently not familiar enough with grails):
Inject grailsApplication.config.apiCredentials into the service in the controller when the service is created?
Provide some form of contructor on the service that allows the credentials to be passed in to the service at instantiation time?
Having the credentials injected into the service is ideal. How could this be done?
The grailsApplication object is available within services, allowing this:
package example
import com.example.ExampleApiClient;
class ExampleService {
def grailsApplication
def relevantMethod() {
def client = new ExampleApiClient(
grailsApplication.config.apiCredentials.baseUrl
grailsApplication.config.apiCredentials.username,
grailsApplication.config.apiCredentials.password
)
return client.action();
}
}
Even though grailsApplication can be injected in services, I think services should not have to deal with configuration because it's harder to test and breaks the Single Responsibility principle. Spring, on the other side, can handle configuration and instantiation in a more robust way. Grails have a dedicated section in its docs.
To make your example work using Spring, you should register your service as a bean in resources.groovy
// Resources.groovy
import com.example.ExampleApiClient
beans {
// Defines your bean, with constructor params
exampleApiClient ExampleApiClient, 'baseUrl', 'username', 'password'
}
Then you will be able to inject the dependency into your service
class ExampleService {
def exampleApiClient
def relevantMethod(){
exampleApiClient.action()
}
}
In addition, in your Config.groovyfile, you can override any bean property using the Grails convention over configuration syntax: beans.<beanName>.<property>:
// Config.groovy
...
beans.exampleApiClient.baseUrl = 'http://example.org'
Both Config.groovy and resources.groovy supports different environment configuration.
For contexts where you can't inject the grailsApplication bean (service is not one of those, as described by Jon Cram), for example a helper class located in src/groovy, you can access it using the Holders class:
def MyController {
def myAction() {
render grailsApplication == grails.util.Holders.grailsApplication
}
}
The best options are (as from grails docs):
1 - Using Spring #Value annotation
import org.springframework.beans.factory.annotation.Value
class WidgetService {
int area
#Value('${widget.width}')
int width
def someServiceMethod() {
// this method may use the width property...
}
}
2 - Having your class implement GrailsConfigurationAware
import grails.config.Config
import grails.core.support.GrailsConfigurationAware
class WidgetService implements GrailsConfigurationAware {
int area
def someServiceMethod() {
// this method may use the area property...
}
#Override
void setConfiguration(Config co) {
int width = co.getProperty('widget.width', Integer, 10)
int height = co.getProperty('widget.height', Integer, 10)
area = width * height
}
}

Resources