Grails - save() failing with MissingMethodExcepition in integration test - grails

I'm learning groovy / grails, and writing my first integration test.
It's currently failing with:
groovy.lang.MissingMethodException: No
signature of method:
com.mangofactory.scurry.User.save() is
applicable for argument types: ()
values: []
My test isn't doing anything fancy:
class UserEventControllerTests extends ControllerUnitTestCase {
protected void setUp() {
super.setUp()
}
protected void tearDown() {
super.tearDown()
}
void testAddingAUser()
{
def user = new User(emailAddress: "martypitt#test.com")
user.save()
}
}
Saving the entity works fine when I do it through the scaffolded pages provided by grails.
What have I missed?

If you want it to be an integration tests it shouldn't extend one of the unit test base classes, so change it to
class UserEventControllerTests extends GroovyTestCase {
...
}
and make sure it's in test/integration, not test/unit.
But it looks like you want to test a controller (it's called UserEventControllerTests) which should extend ControllerUnitTestCase. If that's the case then you should be doing unit tests, but mocking the domain layer (using mockDomain and others) since you want to focus on controller logic, not persistence. Test domain classes in proper integration tests using a database.
This is all described in chapter 10 of the docs: http://grails.org/doc/latest/

Related

Do GORM hook methods work in Grails integration test

I have simple question
Do GORM hooks method (beforeUpdate, afterLoad etc) work during integration tests? Are they evaluated?
I have integration test (my test class extends GroovyTestCase) and as I can see changes that I make in afterLoad method on my domain object doesn't seem to work (domain object stays the same after loading) and when I test it manually (run my app) it works (domain object is changed successfully). Also I cannot see any logs or prints to console from hook methods during integration tests.
Is this expected behavior or I am missing something?
Here is some code:
I have PackageState domain object which has field accountID (Integer).
In PackageState I have afterLoad hook:
def afterLoad() {
this.accountID = 33333
}
My test suite looks something like this :
void "test3"() {
PackageState packageState1 = PackageState.findByAccountID(11111)
assertEquals(33333, packageState1.accountID)
}
Message is :
junit.framework.AssertionFailedError: expected:<33333> but was:<11111>
So seems to me that hook is not called :/ ...
Thanks,
Ivan
You can integration test those event hooks by surrounding the dynamic method (or any other GORM method) by withNewSession as:
class PackageStateSpec extends IntegrationSpec {
PackageState packageState1
void "test something"() {
given:
PackageState.withNewSession{
packageState1 = PackageState.findByAccountID(11111)
}
expect:
packageState1.accountID == 33333
}
}
Events will be registered with a new session every time when tested from integration tests.

Grails integration test cannot invoke method on null service object?

Simple service class, AnalyzerService, calls stored proc in a database.
Attempting to run integration test to ensure service calls the stored proc and correct data is returned after analyzer class operates on it. However, getting the dreaded exception that "Cannot invoke method calculateEstimateNumberOfPositions() on null object". Why is the service object null? What am I missing?
THANK YOU!
package foobar.analyze
import static org.junit.Assert.*
import org.junit.*
import foobar.analyze.AnalyzerService
//#TestFor(AnalyzerService)
class AnalyzerServiceTests {
def AnalyzerService service
def dataSource
#Before
void setUp() { }
#After
void tearDown() { }
#Test
void testcalculateEstimateNumberOfPositions() {
String positionName = "crew"
String city = "Great Neck"
String state = "NY"
int numberOfPositionsSought = 100
int expectedNumberOfPositionsEstimate = 100
def numberOfPositionsEstimate = service.calculateEstimateNumberOfPositions(positionName, city, state, numberOfPositionsSought)
fail (numberOfPositionsEstimate != expectedNumberOfPositionsEstimate)
}
}
Convention. Stick to the convention. Anything out of convention, regarding nomenclature, will create problem during dependency injection.
Convention is to use the service class name as analyzerService instead of service in integration test.
The integration test should look like
class AnalyzerServiceTests extends GroovyTestCase {
//Service class injected only if you
//use the naming convention as below for AnalyzerService
def analyzerService
def dataSource
......
......
}
It was possible to use service in unit test case when you use the test mixin
#TestFor(AnalyzerService)
By using the above in unit test cases, you could use the default service variable in the test cases. This is not the same in case of integration tests.

How to test a controller that has a #Mixin of a Basecontroller

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)
}

Grails integration test setUp and junit annotation

I have some executeQuery in the code for complex group by/having clause so I need an integration test case to test it. Grails 2.1.1 was used.
However, I found several issues:
1. the setUp method is not called automatically before the test.
2. So I add #Before annotation to the setUp method and it can be called now. But the executeQuery statement can't be used now.
java.lang.UnsupportedOperationException: String-based queries like [executeQuery] are currently not supported in this implementation of GORM. Use criteria instead.
It seems I can't use any annotation in the integration test. Otherwise it becomes a unit test case? If I don't use any annotation, the test passed.
Here is the code example.
class JustTests extends GroovyTestCase {
void setUp() {
log.warn "setup"
}
void tearDown() {
log.warn "cleanup"
}
void "test something"() {
// Here is the code to invoke a method with executeQuery
}
}
Thanks.

Changing autoGenerating Grails Test Scaffold to Spock Test

Hi i m trying to change the auto-generated testCases in grails
#TestMixin(GrailsUnitTestMixin)
class KLAKSpec {
void setUp() {
// Setup logic here
}
void tearDown() {
// Tear down logic here
}
void testSomething() {
fail "Implement me"
}
}
to Spock Type test format which is something like this
#TestFor(GrailsUnitTestCase)
class #artifact.name# extends #artifact.superclass# {
def "feature method"() {
setup:
when:
then:
where:
}
}
Althought i have added a _Events.groovy script under the scipt folder and added a Spec.groovy file in artifacts folder which changes the name when i auto generate the list.
Can any one please let me knw how i can change to spec format.
I wrote a blog post on this some time ago: Auto-generate Spock specs for Grails artifacts. The post was written pre-Grails 2 so it's still using the old superclasses rather than #TestFor but it should be easy enough to adapt. We still use this technique on our project where we're still on Grails 1.3.7. It's a bit of a blunt instrument as Grails doesn't expose a unique event for test generation but it works fine.

Resources