7

我有一个域类,它扩展了一个抽象类,它注入了spring 安全核心插件服务。

class Extra extends WithOwner {
    String name
}

abstract class WithOwner {
    transient springSecurityService
    User user

    def getCurrentUser() {
        return springSecurityService.currentUser
    }

    def beforeValidate() {
        if(!user) {
             user = getCurrentUser()
        }
    }

    Boolean isLoggedUserTheOwner(){
        return (user?.id == getCurrentUser()?.id)
    }
}

我想实现一个控制器测试。

@TestFor(ExtraController)
@Mock([Extra, User, UserRole, Role])
class ExtraControllerTests {

    void testEdit() {
        def utils = new TestUtils()
        def user1 = utils.saveUser1()

        populateValidParams(params)
        def extra = new Extra(params)
        extra.user = user1
        assert extra.save() != null

        params.id = extra.id


        def model = controller.edit() // Line 69
        assert model.extraInstance == extra
    }
}

如果我运行上述测试,我会得到:

test-app ExtraController.testEdit --unit --echoOut | 运行 1 个单元测试... 1 of 1 --testEdit 的输出-- | 失败:testEdit(com.softamo.movi​​lrural.ExtraControllerTests) | java.lang.NullPointerException:无法在 com.softamo.movi​​lrural.WithOwner.getCurrentUser(WithOwner.groovy:8) 的 com.softamo.movi​​lrural.WithOwner.isLoggedUserTheOwner(WithOwner.groovy:18) 的空对象上获取属性“currentUser” com.softamo.movi​​lrural.ExtraController.edit(ExtraController.groovy:39) 在 com.softamo.movi​​lrural.ExtraControllerTests.testEdit(ExtraControllerTests.groovy:69) | 完成 1 个单元测试,1 个在 853 毫秒内失败

我曾尝试像这样模拟安全服务但没有成功:

Extra.metaClass.springSecurityService = new MockSpringSecurityService(user1)

甚至嘲笑该方法

Extra.metaClass.getCurrentUser = { return user1 }

知道我该如何解决这个问题。

4

3 回答 3

2

Grails 2.x 支持使用'defineBeans' 闭包为测试环境定义spring bean。它支持控制器等中的依赖注入,我不确定它是否也适用于域对象。从理论上讲,它应该在域对象/控制器/服务之间保持一致

请参阅http://grails.org/doc/latest/guide/single.html#testing -“测试 Spring Beans”部分。

于 2012-04-23T09:51:29.233 回答
1

我发现了一篇关于这个问题的好文章:Inject springSecurityService Into Grails Domain Class for Controller Unit Testing

于 2013-08-12T13:55:32.170 回答
1

这应该有效:

controller.springSecurityService = new SpringSecurityService()

如果要在此服务中模拟 getCurrentUser 方法:

controller.springSecurityService.metaClass.getCurrentUser = { -> return user1 }

我不确定你是否可以->在上面的一行中省略,所以测试一下。如果您想在使用后或另一个测试用例之前清除此模拟方法,请使用:

controller.springSecutiryService.metaClass = null
于 2012-04-23T07:31:49.857 回答