Unit Test fails with GrailsConfigurationException - cannot find responsible line of code - unit-testing

I am writing unit tests for my Grails 3.0.3 application with standard spock framework. Everything as scaffolded by
grails create-app
I created my unit test with
grails create-unit-test
Added manually #TestFor annotation and test logics. I get
mypackage.MyClassSpec > test myMethod method FAILED
org.grails.core.exceptions.GrailsConfigurationException
GIST of My test class (generalized and simplified)
There is no line number in stacktrace after running
grails test-app --stacktrace
How can I find out what is causing this exception?

The TestFor annotation is used to test Grails artefacts (yes, that's how it's spelled in the source code).
The TestFor annotation defines the class under test and will
automatically create a field for the type of class under test. For
example in the above case a "controller" field will be present,
however if TestFor was defined for a service a "service" field would
be created and so on.
The class you were testing is a plain Groovy class, not a Grails controller, service, etc. So, BAM! You got an awkward exception.

Related

Apache shiro unit test with checkPermission passes regardless of stubbed permission

Running spring boot 1.5.12 with Shiro starter 1.4.0
Trying to write up some unit tests to test a static class which checks permissions using the checkPermission of the Subject interface.
I'm mocking the shiro subject and stubbing the isPermitted method to return false for specific permission string... but for some reason, it passes when Subject.checkPermission is executed.
Subject subjectUnderTest = mock(Subject.class);
when(subjectUnderTest.isAuthenticated()).thenReturn(true);
when(subjectUnderTest.isPermitted(eq("review:edit:regional"))).thenReturn(false);
setSubject(subjectUnderTest);
subjectUnderTest.checkPermission("review:edit:regional");
I'm fairly new to Mockito but in this case was expecting AuthorizationException to be thrown by checkPermission given the isPermitted stub returning false.
If i change the implementation to use isPermitted, then test runs as expected..but current implementation is using checkPermission...
The method checkPermission() of the Subject interface will not call isPermitted() on itself but on the abstract AuthorizingRealm. The callchain for checkPermission() is like the following:
Subject.checkPermissions()->
DelegatingSubject.checkPermissions()->
Authoriser.checkPermission()->
AuthorizingRealm.checkPermission()->
AuthorizingRealm.isPermitted()
Therefore, mocking isPermitted() on the Subject will have no effect since checkPermission() will never call it on this object. To achieve the expected behavior, you have to mock the method on the AuthorizingRealm or alternatively on the AuthorizingSecurityManager incase calls to your SecurityManager are available under test.

How to inject log property in Grails 3 unit tests?

I'm trying to upgrade my Grails 2 project to Grails 3. I'm having problems with running tests for code blocks that use logging as it throws NoSuchPropertyException for log property. This was no problem with Grails 2 as the property is automatically injected. How do I get this working in Grails 3? I'm using 3.0.2.
Add the #groovy.util.logging.Slf4j class annotation to your Spec and log will be injected.
I've been doing this in my Groovy classes, I don't know whether this will work for your tests:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
// within my class that I want to call log on
private static final Logger log = LoggerFactory.getLogger(MyClass.class)
// now you can call log from within a method
log.info("Log foo")

Grails Unit testing GORM global constraints

I have an issue where the global constraints setup in the Config are not working when running unit tests.
This is in my Config.groovy:
grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
in my test I have tried this:
static doWithConfig(c){
c.grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
and also in the setupSpec():
grailsApplication.config.grails.gorm.default.constraints={
'*'(nullable:true, bindable:true)
}
All I'm doing in my test is trying to create a domain object from a json string. Is there anything special that I should be doing to get this to work in the Unit test? This is also using the Gorm-MongoDb plugin.

call to .save() on domain class fails with no signature of method .save() in unit test

I'm using Grails 1.3.2 in NetBeans. I have a very simple unit test that fails with this error:
No signature of method: com.maxrecall.maxrequire.domain.Release.save()
is applicable for argument types: (java.util.LinkedHashMap) values:
[[flush:true]] Possible solutions: wait(), any(), wait(long),
isCase(java.lang.Object), use([Ljava.lang.Object;), sleep(long)
The relevant code is:
Release rel = new Release()
...
rel.save(flush:true)
The same code works in BootStrap.groovy. I have tried various variations on .save() (.Save with and without parameters.
It's a unit test, so there's no Spring, Hibernate, etc. You have to mock the behavior you want.
If you're testing persistence, you need to convert the test to an integration test, since testing persistence with unit tests just tests the mocking framework. An integration test uses at a minimum an in-memory database, although you can easily switch that for a test instance of MySQL/Oracle/etc.
If you're testing controllers or other users of your domain classes and just want them to work so you can focus on testing the current class, use mockDomain and the other mock methods available in the Grails unit test base classes.
This is all described in detail in the documentation - see http://grails.org/doc/latest/guide/9.%20Testing.html
There's no grails magic around in a unit test (it's there in an integration test). See "Understanding mockDomain()" here or read the Grails docs.

Grails. mocked data from a unit test is available in an integration test

Im having a failed integration test because of test pollution (tests pass or fail depending on which order they are run in).
What baffles me a bit however is that it seems that a unit test where i have mocked some data with mockDomain(Media.class,[new Movie(...)]) is still present and available in other tests, even integration tests.
Is this the expected behaviour? why doesn't the test framework clean up after itself for each test?
EDIT
Really strange, the documentation states that:
Integration tests differ from unit tests in that you have full access to the Grails environment within the test. Grails will use an in-memory HSQLDB database for integration tests and clear out all the data from the database in between each test.
However in my integration test i have the following code
protected void setUp() {
super.setUp()
assertEquals("TEST POLLUTION!",0,Movie.count())
...
}
Which gives me the output:
TEST POLLUTION! expected:<0> but was:<1>
Meaning that there is data present when there shouldn't be!
Looking at the data that is present int he Movie.list() i find that the data corresponds to data set in a previous test (unit test)
protected void setUp() {
super.setUp()
//mock the superclass and subclasses as instances
mockDomain(Media.class,[
new Movie(id:1,name:'testMovie')
])
...
}
Any idea's of why im experiencing these issues?
It's also possible that the pollution is in the test database. Check the DataSources.groovy to see what is being used for the test environment. If you have it set to use a database where
dbCreate is set to something other than "create-drop", any previous contents of the database could also be showing up.
If this is the case, the pollution has come from an entirely difference source. Instead of coming from the unit tests, it has actually come from the database, but when switching to run the integration tests you get connected to a real database with all the data it contains.
We experienced this problem, in that our test enviroment was set to have dbCreate as "update". Quite why this was set for integration tests puzzled me, so I switched to use dbCreate as "create-drop" and make sure that when running test suites we started with a clean database.