问题
package com.rohan
import grails.test.mixin.*
import spock.lang.Specification
import grails.plugins.springsecurity.SpringSecurityService
import grails.test.mixin.domain.DomainClassUnitTestMixin
import com.rohan.meta.MetaServiceCategory
@TestFor(ProjectDashBoardController)
@Mock([SpringSecurityService,User,Project,MetaServiceCategory,ProjectIntroduction,ProjectDetails,ProjectAdditionalInfo,SPCompany,BuyerCompany,Conversation,ServiceCategory,UserAuthService,TimeSheetService,ProjectService])
class ProjectDashBoardControllerSpec extends Specification {
void "test timeSheets action"() {
given:
BuyerCompany buyerCompany = new BuyerCompany()
Project testProject = new Project(title: "test Project",projectId:"0411",buyerCompany:buyerCompany)
testProject.save()
println "project : "+testProject
when:"When Project Id Given"
controller.params.id = "00411"
controller.timeSheets()
then:
response.redirectUrl.endsWith '/dashboard/index'
}
}
Here is controller code:
class ProjectDashBoardController {
def springSecurityService
def userAuthService
def timeSheets(){
def project=Project.findByProjectId(params.id)
if(project){
def user = userAuthService.getCurrentUser()
// Do Something
} else {
redirect(controller:'dashboard',action:'index')
}
}
}
@OPAL i think that's what u asking
class UserAuthService {
def getCurrentUser(){ def user = springSecurityService.currentUser return user } } And finally I receive the following error:
Cannot get property 'currentUser' on null object
at com.rohan.UserAuthService.getCurrentUser(UserAuthService.groovy:22)
at com.rohan.ProjectDashBoardController.timeSheets(ProjectDashBoardController.groovy:130)
at com.rohan.ProjectDashBoardControllerSpec.test timeSheets action(ProjectDashBoardControllerSpec.groovy:29)
回答1:
I don't see validated answer, maybe it will help somebody else :
With grails, if you want userAuthService or other services (like grails core services or your own) you have several possibilities like :
- Stub/Mock them in a unit test and define the behaviour
- Make your unit test an integration test
1. Stub/Mock them in a unit test
Here with a Stub :
void "test timeSheets action"() {
given:
...your code...
def userAuthService = Stub(UserAuthService)
User currUser = new User(email: "current@current.fr", firstname: "firstname")
// Here we define the behaviour of our Stubbed service :
userAuthService.getCurrentUser() >> currUser
and:"we inject our fake userAuthService"
controller.userAuthService = userAuthService
when:"When Project Id Given"
...your code...
then:
...your code...
}
NOTE : you can use Mock(UserAuthService) in place of Stub(UserAuthService). Then you'll be able to verify in the "then" part that getCurrentUser() has been called once with
1 * userAuthService.getCurrentUser()
2. Make your unit test an integration test
From grails documentation about Testing
Integration tests differ from unit tests in that you have full access to the Grails environment within the test. Grails uses an in-memory H2 database for integration tests and clears out all the data from the database between tests.
回答2:
You declare userAuthService
but I can't see any place it's injected or initialized.
回答3:
If that's a unit test (not integration one) you should just create Mock
or Stub
of your userAuthService
and inject it into the controller. By inject in this specific case just use setter like controller.userAuthService = serviceStub
.
回答4:
void "test timeSheets action"() {
setup:
testUser = new User()
controller.userAuthService = [currentUser: testUser]
given:
BuyerCompany buyerCompany = new BuyerCompany()
Project testProject = new Project(title: "test Project",projectId:"0411",buyerCompany:buyerCompany)
testProject.save()
println "project : "+testProject
when:"When Project Id Given"
controller.params.id = "00411"
controller.timeSheets()
then:
response.redirectUrl.endsWith '/dashboard/index'
}
As part of setup section of your test, Mock Test User and inject to userAuthServices. I had similar problem and it did the fix.
来源:https://stackoverflow.com/questions/24277504/get-current-user-in-grails-spock-unit-testing-which-uses-spring-security