【问题标题】:How to initialise/wire beans in Grails Spock unit tests?如何在 Grails Spock 单元测试中初始化/连接 bean?
【发布时间】:2014-11-18 12:46:39
【问题描述】:

我想测试一个包含 bean 的 Grails 控制器(我会在它工作后将其移至 Service,但我现在只想保持简单)。

//resources.groovy
beans {
    myBean(com.me.MyBean) 
}


// MyBean.java
// this needs to be in java as it is playing with spring-data-neo4j
package com.me;
public class MyBean {
    String show() {
        return "Hello";
    }
}

// TestController.groovy
package com.me

import com.me.MyBean

class TestController {

    def myBean

    def index() {
        render myBean.show()
    }
}


// TestControllerSpec.groovy
package com.me

import grails.test.mixin.TestFor
import spock.lang.Specification

import com.me.*

@TestFor(TestController)
class TestControllerSpec extends Specification {

    def myBean

    def setup() {
        defineBeans {
            myBean(com.me.MyBean) {bean->
                bean.autowire = true
            }
        }
    }

    def cleanup() {
    }

    def "show() returns Hello"() {
        when:
        def rc = controller.myBean.show()
        def rc2 = myBean.show()

        then:
        rc == "Hello"
        rc2 == "Hello"
    }
}

在 TestControllerSpec 中,myBean 为空。 controller.myBean 也是空的。我认为这是因为 Spring 没有拾取 bean 并将其连接起来。我认为在单元测试中并非所有 spring bean 都可用,但是我需要做什么才能让 controller.myBean 被实例化并正确连接?

【问题讨论】:

  • 你可能不想在单元测试中这样做。您可以在 setup 方法中模拟或存根它:def setup() { controller.myBean = Stub(MyBean) },然后使用 interactions 测试您的控制器。
  • 同意,但是 show() 在我的真实代码中实际上正在做的是写入内存中的图形数据库。我想检查我的方法是否确实导致将真实数据写入数据库,而不是我的方法调用写入数据库的方法(即通过模拟)。 (当然,在这个过程中,为了更好地了解 Spring 的实际工作原理)。
  • 但是为 MyBean 编写一个单元测试并在那里执行该测试不是更好吗?否则,在这种情况下,集成或功能步骤可能更有意义..
  • 是的 - 谢谢,您的回答让我发现了 Grails 中集成和功能测试之间的区别。我还没有找到在 src/java 中编写 bean 并在 Grails 中进行单元测试的示例,因此我将在 SO 上发布一个单独的问题。

标签: spring grails spring-data spock


【解决方案1】:

你一定是在模仿下面的 myBean

def myBean = Mock(MyBean)

MyBean myBean = Mock()

如果需要,然后根据您的需要存根方法如下:

myBean.show >> "test data"

然后将其分配给已经为您模拟的控制器对象。

controller.myBean = myBean

你去吧。

或者您可以选择存根 myBean 并提供存根实现。例如,

MyBean myBean = Stub(){
show() >> {return "sample text"}
}
controller.myBean = myBean

这样做的原因是我们没有测试应用程序实体(如控制器、视图或域)的集成,但我们正在测试单个单元,即方法,因此我们应该只是测试它,而对于集成,我们应该使用集成除了在正常情况下不需要任何模拟之外,所有测试用例都相似。

编辑:

发现了另一个有用的功能来使用defineBeans闭包来模拟服务或bean,如下所示:

        defineBeans {
            adapter(Adapter)
            helperService(HelperService)
        }

这将允许从grailsApplication 访问bean。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-06
    • 2014-06-21
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    相关资源
    最近更新 更多