How to mock a service injected in a domain class from a Controller Test Class?

I have a domain class which extends an abstract class which injects the spring security core plugin service.

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

I want to implement a controller test.

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

If I run the above test I get:

test-app ExtraController.testEdit --unit --echoOut | Running 1 unit test... 1 of 1 --Output from testEdit-- | Failure: testEdit(com.softamo.movilrural.ExtraControllerTests) | java.lang.NullPointerException: Cannot get property 'currentUser' on null object at com.softamo.movilrural.WithOwner.getCurrentUser(WithOwner.groovy:8) at com.softamo.movilrural.WithOwner.isLoggedUserTheOwner(WithOwner.groovy:18) at com.softamo.movilrural.ExtraController.edit(ExtraController.groovy:39) at com.softamo.movilrural.ExtraControllerTests.testEdit(ExtraControllerTests.groovy:69) | Completed 1 unit test, 1 failed in 853ms

I have tried without success to mock the security service like this:

Extra.metaClass.springSecurityService = new MockSpringSecurityService(user1)

or even mocking the method

Extra.metaClass.getCurrentUser = { return user1 }

Any idea how could I work around this issue.


Grails 2.x supports defining spring beans for test environments using 'defineBeans' closure. It supports dependency injection in controllers etc, I am not sure if it works for domain objects as well. Theoretically it should be consistent across domain objects/controllers/services

See http://grails.org/doc/latest/guide/single.html#testing - The 'Testing Spring Beans' section.


This should work:

controller.springSecurityService = new SpringSecurityService()

If you want to mock getCurrentUser method in this service:

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

I'm not sure if you can ommit -> in a line above, so test it. If you want to clear this mocked method after use or before another test case use this:

controller.springSecutiryService.metaClass = null

我发现了一个关于这个问题的好文章:将springSecurityService注入到Grails域类中以进行控制器单元测试

链接地址: http://www.djcxy.com/p/58992.html

上一篇: 用于在数据库中查找相似图像的度量标准

下一篇: 如何模拟从Controller测试类中的域类中注入的服务?