8

我有更一般的问题。使用 Spock 时,我应该使用哪个框架或实现在 Grails 2.x 中进行模拟?

我知道大量的模拟风格:利用 Groovy 元类、Grails mockFor()、Groovy Mock()、Groovy 闭包风格等。它们各有优缺点。但我不明白的是,某些模拟风格在我无法确定的某些情况下有效(即 mockFor() 适用于某些实现而不适用于其他实现)。

目前我有两个类似的服务方法模拟实现。

这个有效:

@TestFor(MyController)
@Mock([MyDevice])
class MyControllerSpec extends ControllerSpec {

void "test st."() {
      def myService = mockFor(MyService)
      myService.demand.myMethod() { def st ->
         return "test"
      }
      controller.myService = myService.createMock()
}
}

但是,此实现不起作用:

@TestFor(MyController)
@Mock([MyDevice])
class MyControllerSpec extends ControllerSpec {

void "test st."() {
      def yourService = mockFor(YourService)
      yourService.demand.yourMethod() { def st ->
         return "test"
      }
      controller.yourService = yourService.createMock()
}
}

服务实现和从控制器调用非常相似。那么在 Grails 中模拟的最佳实践是什么?或者是否有任何 Grails 的良好模拟框架可以节省我弄清楚如何模拟的时间?

感谢您的任何建议!:-)

马特奥

4

1 回答 1

8

当您使用 spock 框架进行测试时,请尝试利用框架本身提供的选项和样式。

Spock 框架有助于实现 BDD [行为设计开发]。我的意思是行为,您可以将业务接受场景与开发周期紧密结合。

我试图用 Spock 编写您的测试用例,因为它可以重写为:

@TestFor(MyController)
class MyControllerSpec extends ControllerSpec {

    void "test service method in called once and only once"(){
        //Defines the behavior of setup
        setup: "Only one invocation of service method" 
            def myService = Mock(MyService){
                //Make sure serviceMethod is called only once from the controller
                //Beauty of Spock is that you can test the cardinality of
                //method invocations.  
                1 * serviceMethod() >> "Hello"
            }
            controller.myService = myService

            //The above process can be followed 
            //for stubbing/mocking 'YourService' and 
            //then injecting it to controller like
            //controller.yourService = yourService

        //Defines the behavior of action
        when: "controller action is called" 
            controller.myAction()

        //Defines the behavior of expected results
        then: "Expect the stubbed service method output" 
            controller.response.contentAsString == "Hello"
    }
}

//Controller
def myAction() {
    render myService.serviceMethod()
}

如果您在上面看到,您定义了每个步骤中的行为。从企业的角度来看,这些行为将由 BA 或利益相关者驱动。通过这种方式,您可以遵守 ATDD/BDD(验收测试驱动开发/行为测试驱动开发),并最终为您的项目遵守 TDD(测试驱动开发)。

有关如何有效使用 spock 框架的更多详细信息,请访问 spock 框架文档

于 2013-07-26T02:15:56.653 回答