I'm running into a problem when running integration tests in Grails. One of the domain classes in the project has a method that accesses the grailsApplication.config property. We have an integration test for one of our services that call this method in the domain class. When the test is run on its own using the command
grails test-app integration: com.project.MyTestSpec
The test runs fine and the domain class can access grailsApplication. However when the whole test suite is run using:
grails test-app integration
then the test fails with the error
java.lang.NullPointerException: Cannot get property 'config' on null object
When trying to access grailsApplication.config. It seems that when the tests are all run together grailsApplication is not being injected into the domain class. Has anyone come across this issue before?
From what I have read it seems to be a test pollution issue but as there is no setup happening in each integration test the problem is hard to track down.
I came across this issue with grails 3. If you are testing a Domain, you have to setup (testing with spock) at the begining of the test:
def setup() {
Holders.grailsApplication = new DefaultGrailsApplication()
Holders.grailsApplication.config.property.code = '1234'
}
I'm not sure what the issue is, but this must be a test pollution issue where yours any one of the test case is doing something with grailsApplication using meta class. Because this seems to work fine for me.
As a workaround you can avoid using injected grailsApplication and use the Holders class instead like the following:
package com
import grails.util.Holders
class User {
// def grailsApplication
String email
String name
String getTitle() {
return Holders.getConfig()["app.title.prefix"] + name
// Or
//return Holders.grailsApplication.config["app.title.prefix"] + name
}
}
This way, you are not dependent upon the dependency injection.
I had the same issue and found that my integrationstest implemented ServiceUnitTest<> which caused the problem.
Related
I'm using grails 3.2.9 version. And trying to create custom command. I need a command because I need to have access to spring beans. So the code is simply like this:
class MyTestCommand implements GrailsApplicationCommand {
boolean handle() {
def bean = applicationContext.getBean('myBean')
bean.doSomething()
return true
}
When I run it as
grails run-command my-test
I'm getting an error: "Missing application class name and script name arguments"
I'am able to add application class as last param and everything seems works, but the question is, why I should add it? Does grails doesn't know about its Main Application class? I did some research about and there is no answers, in each examples i se only command name without Application class. But as I understand from this source we should pass main class always. Am I missed something?
I am building a Grails REST application and I have written my Functional Tests using Spock.
Note that these functional tests are for REST services only.
class LoginFunctionalSpec extends Specification {
def setUp() {
// here I want to access grailsApplication.config
}
}
I have already tried the following approaches:
Injecting grailsApplication (by defining as class level variable), but nothing get's injected.
Using ApplicationHolder.application.config but it has been deprecated and the suggested approach was the previous point.
Tried using plugin remote-control:1.4 but although grails console showed the plugin as installed I didn't find the class RemoteControl. Also I was never sure of this approach
I tried reading grails-app/conf/Config.groovy as a file (as explained here) but got a FileNotFoundException.
But none of them provide me grailsApplication.config inside my functional test.
Is there any way to achieve this ?
UPDATE
#dmahapatro
I am not using Geb because I am testing REST services and there is no browser automation required.
As I said in point#1 grails Application is not being auto-injected.
class LoginFunctionalSpec extends Specification {
def grailsApplication
def setUp() {
def port = grailsApplication.config.mongo.port //throws NPE
}
}
It throws a NPE saying that config property is being invoked on null object.
I think you do not need to inject anything explicitly. grailsApplication is available in the tests by default.
class LoginFunctionalSpec extends Specification {
def setUp() {
grailsApplication.config.blah //should work
}
}
Note-
Spock does not provide direct support for functional tests. You need to use Geb for proper functional tests.
Are you running your test in integration test phase or functional test phase?
You need to extend from IntegrationSpec to get autowiring in integraton test phase but you are talking about functional tests here... Because of grails running your tests in the same JVM as the application under tests you don't really need to use RemoteControl but I always do anyway in my functional tests as it seems much cleaner to me and is a really powerful technique if your tests and application under tests are not running in the same JVM.
so I think I'm perhaps not fully understanding how you would use an IOC container for doing Integration tests.
Let's assume I have a couple of classes:
public class EmailComposer : IComposer
{
public EmailComposer(IEmailFormatter formatter)
{
...
}
...
public string Write(string message)
{
...
return _formatter.Format(message);
}
}
OK so for use during the real application (I'm using autofac here) I'd create a module and do something like:
protected override void Load(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<HtmlEmailFormatter>().As<IEmailFormatter>();
}
Makes perfect sense and works great.
When it comes to Unit Tests I wouldn't use the IOC container at all and would just mock out the formatter when I'm doing my tests. Again works great.
OK now when it comes to my integration tests...
Ideally I'd be running the full stack during integration tests obviously, but let's pretend the HtmlEmailFormatter is some slow external WebService so I decide it's in my best interest to use a Test Double instead.
But... I don't want to use the Test Double on all of my integration tests, just a subset (a set of smoke-test style tests that are quick to run).
At this point I want to inject a mock version of the webservice, so that I can validate the correct methods were still called on it.
So, the real question is:
If I have a class with a constructor that takes in multiple parameters, how do I make one of the parameters resolve to a an instance of an object (i.e. the correctly setup Mock) but the rest get populated by autofac?
I would say you use the SetUp and TearDown (NUnit) or ClassInitialize and ClassCleanup (MSTest) for this. In initialize you register your temporary test class and in cleanup you restore to normal state.
Having the DI container specify all the dependencies for you has the benefit of getting an entire object graph of dependencies resolved. However if there's a single test in which you want to use a different implementation I would use a Mocking framework instead.
So I have a grails domain class:
class Message
{
Inbox inbox
Boolean hasBeenLogicallyDeletedByRecipient
...
static belongsTo = [
inbox:Inbox,
...
]
static constraints = {
hasBeenLogicallyDeletedByRecipient(nullable:false)
...
}
}
I would like to use a dynamic finder as follows:
def messages = Message.findAllByInboxAndHasBeenLogicallyDeletedByRecipient(
inbox, false, [order:'desc',sort:'dateCreated'])
This works fine running a unit test case in STS 2.6.0.M1 against grails 1.2.1;
Spinning up the web app, it fails because of the By in hasBeenLogicallyDeletedByRecipient (I'm guessing it has confused the dynamic finder parsing when building up the query).
I can use a criteria builder which works in the app:
def messages = Message.withCriteria {
and {
eq('inbox', inbox)
eq('hasBeenLogicallyDeletedByRecipient', false)
}
order('dateCreated', 'desc')
}
But since withCriteria is not mocked, it doesn't immediately work in unit tests, so I could add the following to the unit test:
Message.metaClass.static.withCriteria = { Closure c ->
...
}
Is the criteria/unit test mocking the best/accepted approach? I don't feel completely comfortable with mocking this, as it sidesteps testing the criteria closure.
Ideally, I'd rather use the dynamic finder - is there a succinct way to make it work as is?
If there is no way around it, I suppose the field name could be changed (there is a reason why I don't want to do this, but this is irrelevant to the question)...
UPDATE:
Here's the stacktrace when I try to use findAllByInboxAndHasBeenLogicallyDeletedByRecipient() inside the app - notice how it appears to get the last By and treat everything else between it and findAll as a property. i grazed on http://grails.org/OperatorNamesInDynamicMethods but it doesn't mention anything about By being verboten.
org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [byInboxAndHasBeenLogicallyDeleted] for class [class xxx.Message]
at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController:53)
at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController)
at java.lang.Thread.run(Thread.java:662)
Testing the database querying is really an Integration test, not a unit test. Is your test in /test/unit or /test/integration ? - I'd expect the 'withCriteria' to be fully functional in the integration tests, but not in unit tests.
From the grails docs ( http://grails.org/doc/latest/ ), section 9.1:
Unit testing are tests at the "unit"
level. In other words you are testing
individual methods or blocks of code
without considering for surrounding
infrastructure. In Grails you need to
be particularity aware of the
difference between unit and
integration tests because in unit
tests Grails does not inject any of
the dynamic methods present during
integration tests and at runtime.
In a Grails 1.1 plugin, I'm trying to load a class from the main application using the following code:
class MyClass {
static Map getCustomConfig(String configName){
return new ConfigSlurper().
parse(ApplicationHolder.application.classLoader.loadClass(configName))
}
}
Where configName is the name of the class in $MAIN_APP/grails-app/conf containing the configuration info. However, when the code above runs within a unit test applicationHolder.application returns null, causing the method above to throw a NullPointerException. A Grails JIRA issue was created for this problem, but it has been marked as fixed despite the fact that problem appears to still exist.
I know that within the plugin descriptor class I can access the main application (an instance of GrailsApplication) via the implicit application variable. But the code shown above is in not in the plugin descriptor.
Is there a way that I can load a class from the main application within a plugin (but outside the plugin descriptor)?
Thanks,
Don
It turns out there are 2 possible answers.
The Right Answer
GrailsApplication is not available in unit tests, so for the code above to work it should be an integration test
The Hack that Works
Change
parse(ApplicationHolder.application.classLoader.loadClass(configName))
to
parse(MyClass.classLoader.loadClass(configName))