Recently came across with a weird scenario, that dependency injection for a service within a service, threw NPE while running test-app
Reason for service-in-service injection is to make the GORM/criteriaBuilder as DRY as possible. So following are my two services.
Following class SearchService1.groovy is implemented to provide search capability.
class SearchService1{
def search = { ...//Calls to local closures to build a dynamic criteria }
...
}
Class SearchService2.groovy uses the search closure of SearchService1 class
class SearchService2{
def searchService1
...
def searchEntity(){
searchService1.search()
}
}
Now, the above stated code works pretty well in run-app mode.
But for Integration test written for SearchService2 throws NPE as follows :
Cannot invoke method searchEntity() on null object
java.lang.NullPointerException: Cannot invoke method search() on null object
at com.myapp.service.SearchService2.searchEntity(SearchService2.groovy:326)
at com.myapp.service.SearchService2$searchEntity$0.callCurrent(Unknown Source)
at com.myapp.service.SearchService2.searchEntity(SearchService2.groovy:295)
at com.myapp.service.SearchService2$searchEntity.call(Unknown Source)
at com.myapp.integration.SearchService2Tests.testWhenSearch(SearchService2Tests.groovy:125)
Am I missing something very basic here ? Any thoughts are greatly appreciated. Many Thnx :)
Snippet from TestClass :
class SearchService2Tests extends GroovyTestCase{
...
def searchService2
...
void testWhenSearch(){
def resultSet = searchService2.searchEntity() //This is the line throwing NPE
...
}
}
Woah ! Got rid of this stupid error by this workaround.
To TestClass, inject the searchService1 to searchService2 object like this :
def searchService2
def searchService2.searchService1 = new SearchService1()
But come on ! Is this the right way to do it ? Can anyone explain the above error by the way, that why a Service-in-Service is not instantiated while running test-app.
try this:
class SearchService2Tests extends GroovyTestCase {
...
def searchService1
def searchService2
...
void testWhenSearch(){
def resultSet = searchService2.searchEntity()
...
}
}
but use standard Grails service naming convention and placement
Related
Suppose the following situation...
I have to perform a process which takes a lot of time (about 1 hour)
and I do not want the user of my application to wait until it ends.
The business logic of this process is encapsulated in several services.
So:
class MyService{
def myService2
def myService3
public doSomething(){
myService2.doSomething()
myService3.doSomething()
}
}
class MyController{
def myService
def anAction(){
myService.doSomething()
redirect(action:'index')
}
}
I want the call to my service to be asynchronous.
I tried to create an asynchronous service as indicated by the Grails documentation, using #DelegateAsync.
class AsyncMyService {
#DelegateAsync MyService myService
}
class MyController{
def asyncMyService
def anAction(){
asyncMyService.doSomething()
.onComplete { List results ->
println "completed!"
}
redirect(action:'index')
}
}
But I get the following error when compiling my application:
Caused by ConversionNotSupportedException: Failed to convert property value of type
'MyService2$$EnhancerBySpringCGLIB$$f08a1b38' to equired type 'grails.async.Promise'
for property 'myService2'; nested exception is java.lang.IllegalStateException: Cannot
convert value of type [MyService2$$EnhancerBySpringCGLIB$$f08a1b38] to required type
[grails.async.Promise] for property 'myService2': no matching editors or conversion
strategy found
Any ideas to solve this problem?
Thanks!
Relating to Accessing grails application config from a quartz job:
Apparently, DI doesn't happen prior to the creation of a job. I'm guessing this is the same with other grails artefacts (couldn't spot relevant documentation).
In my particular case, I was aiming to load a property from config and expose that property from the job class. In general though, it seems a valid use-case to me, that artefacts will load configuration, and then return those properties via API.
I'm wondering then, how could this be achieved when a class cannot rely on access to grailsApplication.config at construction.
Thanks
Try with:
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
class MyJob {
def execute() {
def myConfigVar = CH.flatConfig.get('my.var.setup.in.config.groovy')
...
}
}
OR
import grails.util.Holders
class MyJob {
def execute() {
def myConfigVar = Holders.config.my.var.setup.in.config.groovy
...
}
}
I've created a BaseController that I mixinto other Controllers.
Example:
class BaseController () {
def somemethod () {
return "some method"
}
}
#Mixin(BaseController)
class MyController {
def getsomething() {
def test = somemethod()
return test
}
}
I'm trying to write a test case for MyController however, it fails because it can't find somemethod.
My test currently looks like this
#TestFor(MyController)
class MyControllerSpec extends Specification {
def "test getsomething" () {
when:
def m = controller.getsomething()
then:
response.contentAsString == "some method"
}
}
But I keep getting errors like these:
No signature of method: somemethod() is applicable for argument types: () values: []
Question
How can I write spock test for MyController so that it finds somemethod as well
Does using #TestMixin(BaseController) in the Spock test for MyController work?
Ans:- No, it is not required.
UPDATE
There is a small modification required in MyController. Use render instead of return. Here is the detail:
class BaseController {
def someMethod() {
"Some Method"
}
}
import grails.util.Mixin
//Remember to use Grails #Mixin instead of Groovy #Mixin
#Mixin(BaseController)
class MyController {
def getSomething() {
def test = someMethod()
render test
}
}
//Unit Test
#TestFor(MyController)
class MyControllerUnitSpec extends Specification {
void "test get something"() {
when:
controller.getSomething()
then:
response.contentAsString == "Some Method"
}
}
//Controller Integration Test
import grails.plugin.spock.ControllerSpec
class MyControllerIntSpec extends ControllerSpec {
void "test get something integration"() {
when:
controller.getSomething()
then:
controller.response.contentAsString == "Some Method"
}
}
Notes:-
I found some difficulties while testing which are listed below:-
The above tests passed with an initial run. But, when I changed render to return just to see my tests failing, I got compilation errors because of the Grails #Mixin I used in MyController (two version of withFormat). Sometimes I think it does not play well. Changing the mixin to Groovy #Mixin everything went good. I did not like that. I had to stick to Grails #Mixin. Apparently and surprisingly, doing a grails clean && grails compile eradicated the issue. I was able to use Grails #Mixin properly. I am still looking at this discrepancy.
If the above problem were persistent, I would have thought of adding runtime mixin in the setup() method in unit test.
Like
def setup(){
//I would not like to do the same in Integration test
//Integration test should do it for me atleast.
MyController.mixin BaseController
}
I used ControllerSpec instead of IntegrationSpec in integration test. Seems like injection and convention is maintained better in ControllerSpec for controllers. If you see, nowhere am I instantiating MyContoller in the int test.
I have not tested it in normal Junit's Unit and Integration tests, they should be good as well.
My strong advice is to not use mixins in Grails at all. It generates faulty bahvior in tests. Also you need an extra code to apply these mixins for tests, which is bad.
For further information read this replay: http://grails.1312388.n4.nabble.com/grails-2-2-2-upgrade-from-2-2-0-breaks-mixin-on-controller-tp4645461p4645466.html, which applies to mixins in Grails in general, or take look of many issues reported in comments of this issue: http://jira.grails.org/browse/GRAILS-8652 (classes lose their mixins during unit tests).
Based on the answers in this thread, http://grails.1312388.n4.nabble.com/Testing-a-controller-that-has-a-Mixin-td4645595.html
I ended up using,
void setup() {
MyController.mixin(BaseController)
}
Updated post:
In a Controller if I do this:
def obj = new Test(name:"lol")
obj.save(flush:true)
obj.name = "lol2"
//a singleton service with nothing to do with obj
testService.dostuff()
/*
"obj" gets persisted to the database right here
even before the next println
*/
println "done"
Can anyone please explain me why is this happening with Grails 1.3.7 and not with Grails 2? What is the reason?
I know I could use discard() and basically restructure the code but I am interested in what and why is happening behind the scenes. Thanks!
Old post:
I have a test Grails application. I have one domain class test.Test:
package test
class Test {
String name
static constraints = {}
}
Also I have a service test.TestService:
package test
class TestService {
static scope = "singleton"
static transactional = true
def dostuff() {
println "test service was called"
}
}
And one controller test.TestController:
package test
class TestController {
def testService
def index = {
def obj = new Test(name:"lol")
obj.save(flush:true)
obj.name = "lol2"
testService.dostuff()
println "done"
}
}
So what I do:
Create a domain object
Change one of it's properties
Call a singleton service method
What I would expect:
Nothing gets persisted to the db unless I call obj.save()
What happens instead:
Right after the service call Grails will do an update query to the database.
I have tried the following configuration from this url: http://grails.1312388.n4.nabble.com/Turn-off-autosave-in-gorm-td1378113.html
hibernate.flush.mode="manual"
But it didn't help.
I have tested it with Grails 1.3.7, Grails 2.0.3 does not have this issue.
Could anyone please give me a bit more information on what is exactly going on? It seems like the current session has to be terminated because of the service call and because the object is dirty it is getting automatically persisted to the database after the service call. What I don't understand that even with the manual flush mode configuration in Hibernate does not help.
Thanks in advance!
I'm not sure what about that thread you linked to made you think it would work. They all said it wouldn't work, the ticket created has been closed as won't fix. The solution here is to use discard() as the thread stated.
I am having problems when using dependency injection with Services in Grails.
class ExampleService{
def example2Service
def example3Service
def method1(){
def result = example2Service.method2()
}
}
class ExampleService{
def example3Service
def method2(){
def result = example3Service.method3()
return result
}
}
class Example3Service{
def method3(){
return true
}
}
Basically in Example2Service, I am getting a Null Pointer Exception when trying to call method3 in Example3Service.
I would appreciate any help than anybody can give me with this issue
thanks
Dependency Injection needs to be initialized. (The same applies to other kinds of runtime meta programming, like augmenting Domain classes with their save() and validate() methods.)
A Grails application will be initialized when
being run from the grails run-app command
being run after having been deployed to a web server
being run from the grails test-app command (integration tests, only; unit tests do not trigger initialization).
Involved classes are not initialized when
executing a single Groovy file (i.e., by using groovy, groovysh, or groovyConsole)
or when executing a unit test.
The following as an integration test should work:
class Test2ServiceTests extends GroovyTestCase {
def test2Service
void testMethod2() {
assert test2Service.method2() == true
}
}