Grails Spring 安全测试

Posted

技术标签:

【中文标题】Grails Spring 安全测试【英文标题】:Grails Spring Security Testing 【发布时间】:2012-09-30 04:35:56 【问题描述】:

我在我的项目中使用 Grails Spring Security 插件,现在想要对我的代码进行单元测试。我的控制器中有以下代码:

def index() 
    redirect action: 'show', params: [id: springSecurityService.currentUser.id]

我的测试类有以下代码:

void testIndex()       
    controller.index()
    assert "/user/list" == response.redirectedUrl

此测试失败:

| Running 8 unit tests... 1 of 8
| Failure:  testIndex(xxx.UserControllerTests)
|  java.lang.NullPointerException: Cannot get property 'currentUser' on null object
    at xxx.UserController.index(UserController.groovy:12)
    at xxx.UserControllerTests.testIndex(UserControllerTests.groovy:19)

如何在测试用例中验证 Spring Security 用户?你会如何编写单元测试?

【问题讨论】:

【参考方案1】:

您对springSecurityService 的引用似乎为空。只要您的控制器中有一个名为springSecurityService 的字段,就应该注入它。您是否仅在索引方法中将其用作局部变量并且没有将其声明为字段?

我的UserController如下:

class UserController 

    /**
     * Dependency injection for the springSecurityService.
     */
    def springSecurityService

    ....
 

更新

根据您对此答案的 cmets,您确实在控制器中声明了 springSecurityService 字段。我使用了我的工作应用程序并尝试了一个测试,该测试使用我的控制器方法反映了你的应用程序:

@TestFor(UserController)
class UserControllerTests 

    void testSomething() 
        controller.register()
    

我也遇到了 NullPointerException。根据 Burt 的回答(我不知道这一点),我认为 springSecurityService 实例在单元测试执行的上下文中为空。

【讨论】:

在我的控制器中我有:class UserController def springSecurityService ... 我应该在 ControllerTest 中写下来吗? @user1726376 不,您不应该在 ControllerTest 中使用它。我只是确保您有对 springSecurityService 的引用,因为您收到错误消息“无法在空对象上获取属性 'currentUser'”。【参考方案2】:

对于这么简单的事情,我不会为复杂的模拟而烦恼,一个简单的

controller.springSecurityService = [currentUser:[id:1]]

就足够了。

【讨论】:

这不起作用。我得到org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'currentUser=id=1' with class 'java.util.LinkedHashMap' to class 'grails.plugin.springsecurity.SpringSecurityService' due to: groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: currentUser for class: grails.plugin.springsecurity.SpringSecurityService @lmo 我建议的模拟只有在您的控制器中使用 def springSecurityService 时才有效,如果您有类型化声明 SpringSecurityService springSecurityService 则它将不起作用【参考方案3】:

您必须使用功能测试来确保安全。单元测试使用模拟但没有可用的插件或真正的请求。 Spring Security 是使用过滤器链实现的,因此您需要一个真正运行的服务器。如果您使用模拟,您只是在测试模拟。

【讨论】:

以上是关于Grails Spring 安全测试的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 grails 在单元测试中模拟 springSecurityService

Grails,从 Acegi 升级到 Spring 安全插件

Grails - SSL 和 Spring 安全核心

grails spring安全休息插件

Grails - Spring 安全 ldap 活动目录身份验证 - 凭据错误错误

Groovy:使用 Grails 和 Spring 安全核心插件时出现意外令牌