Grails集成测试 - getBean()的Null对象

时间:2013-12-16 22:11:52

标签: grails testing

我无法弄清楚为什么我的集成测试会抛出异常。

集成测试##

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)

|完成了3次集成测试,5次在980ms失败

1 个答案:

答案 0 :(得分:4)

您在集成测试中使用单元测试注释 - 这将导致许多问题。通常,在进行集成测试时,如果要使用JUnit3样式的测试,则可以扩展GroovyTestCase,或者使用JUnit4注释,或者使用Spock并扩展IntegrationSpec。

对于NPE,无论您使用的是正确的单元测试还是集成测试,您都需要自己管理控制器的依赖关系,因为您使用new明确创建它并且不作为预接线访问它春豆。但是集成测试确实支持依赖注入,所以只需在测试中添加控件中的字段,在setUp或单个方法中,您可以在控制器中设置这些bean,例如。

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

另请注意,您无需在tearDown()中清理数据 - 在测试方法结束时回滚的事务中运行集成测试。