Reputation: 1506
I cannot figure out why my integration tests here are throwing exceptions.
package sample
import grails.test.mixin.*
import org.junit.*
/**
* See the API for {@link grails.test.mixin.web.ControllerUnitTestMixin} for usage instructions
*/
@TestFor(UserController)
class UserControllerTests extends GroovyTestCase {
User user
UserController uc
void setUp() {
//Save a User
user = new User(userName: "User1", firstName: "User1FN", lastName: "User1LN")
user.save()
//Set up UserController
uc = new UserController()
}
void tearDown() {
user.delete()
}
/**
* Test the UserController.handleLogin action.
*
* If the login succeeds, it will put the user object into the session.
*/
void testHandleLogin() {
//Setup controller paramaters
uc.params.userName = user.userName
//Call the action
uc.handleLogin()
//if the action functioned correctly, it put a user object into the session
def sessUser = uc.session.user
assert sessUser
assertEquals("Expected ids to match", user.id, sessUser.id)
//And the user was redirected to the Todo Page
assertTrue uc.response.redirectedUrl.startsWith("/todo")
}
/**
* Test the UserController.handleLogin action.
*
* If the login fails, it will redirect to login and set a flash message.
*
*/
void testHandleLoginInvalidUser() {
//Setup controller parameters
uc.params.userName = "Invalid_Name"
//Call the action
uc.handleLogin()
assertEquals "/user/login", uc.response.redirectedUrl
def message = uc.flash.message
assert message
assert message.startsWith("User not found")
}
/*
* Test the UserController.logout action
*
* If the logout action succeeds, it will remove the user object from the session.
*/
void testLogout (){
//Make a user logged into session
uc.session.user = user
//Call the action
uc.logout()
def sessUser = uc.session.user
assertNull ("Expected session user to be null", sessUser)
assertEquals "/user/login", uc.response.redirectedUrl
}
}
| Loading Grails 2.2.3
| Configuring classpath.
| Environment set to test.....
| Packaging Grails application.....
| Packaging Grails application.....
| Compiling 1 source files.
| Running 3 integration tests... 1 of 3
| Running 3 integration tests... 2 of 3
| Failure: testHandleLoginInvalidUser(sample.UserControllerTests)
| java.lang.NullPointerException: Cannot invoke method getBean() on null object
at grails.test.mixin.web.ControllerUnitTestMixin$_mockController_closure3.doCall(ControllerUnitTestMixin.groovy:304)
at grails.test.mixin.web.ControllerUnitTestMixin.mockController(ControllerUnitTestMixin.groovy:311)
| Failure: testHandleLoginInvalidUser(sample.UserControllerTests)
| java.lang.NullPointerException: Cannot invoke method delete() on null object
at sample.UserControllerTests.tearDown(UserControllerTests.groovy:25)
| Running 3 integration tests... 3 of 3
| Failure: testLogout(sample.UserControllerTests)
| java.lang.NullPointerException: Cannot invoke method getBean() on null object
at grails.test.mixin.web.ControllerUnitTestMixin$_mockController_closure3.doCall(ControllerUnitTestMixin.groovy:304)
at grails.test.mixin.web.ControllerUnitTestMixin.mockController(ControllerUnitTestMixin.groovy:311)
| Failure: testLogout(sample.UserControllerTests)
| java.lang.NullPointerException: Cannot invoke method delete() on null object
at sample.UserControllerTests.tearDown(UserControllerTests.groovy:25)
| Failure: sample.UserControllerTests
| java.lang.NullPointerException: Cannot invoke method isActive() on null object
at grails.test.mixin.support.GrailsUnitTestMixin.shutdownApplicationContext(GrailsUnitTestMixin.groovy:234)
| Completed 3 integration tests, 5 failed in 980ms
Upvotes: 1
Views: 1270
Reputation: 75671
You're using unit test annotations in an integration test - that will cause lots of problems. In general when doing integration tests you extend GroovyTestCase if you want to use JUnit3-style tests, or nothing and use JUnit4 annotations, or use Spock and extend IntegrationSpec.
As for the NPEs, whether you're using proper unit tests or integration tests, you need to manage the controller's dependencies yourself since you explicitly create it with new
and don't access it as a pre-wired Spring bean. But the integration test does support dependency injection, so just add fields in your test for whatever you need in the controller, and in setUp
or in individual methods you can set those beans in the controller, e.g.
class UserControllerTests extends GroovyTestCase {
def grailsApplication
def someSpringBean
def someOtherSpringBean
private UserController uc = new UserController()
protected void setUp() {
super.setUp()
user = new User(userName: "User1", firstName: "User1FN", lastName: "User1LN").save()
//Set up UserController
uc.applicationContext = grailsApplication.mainContext
uc.someSpringBean = someSpringBean
uc.someOtherSpringBean = someOtherSpringBean
}
...
Also note that you don't need to cleanup your data in tearDown()
- integration tests run in a transaction that's rolled back at the end of the test method.
Upvotes: 4