【问题标题】:how to test grails 3 controller with services that have another services inject into them?如何使用有其他服务注入其中的服务来测试 grails 3 控制器?
【发布时间】:2016-03-04 17:33:18
【问题描述】:

在控制器的单元测试用例中,我只能注入在相应控制器中使用的服务。但是如果说控制器中的一个服务注入另一个服务,那么我的测试用例会失败,即无法在 null 上调用服务方法对象。

@TestFor(MyController)
@Mock(MyService)
class MyControllerSpec extends Specification {
    void "test something"(){
        when:
            controller.method1();
        then:
            //something
    }

}

class MyController(){
    MyService myService

    void method1(){
        myService.serviceMethod()       
    }   
}

class MyService(){
    AnotherService anotherService
    void serviceMethod(){
        anotherService.anotherServiceMethod()
    }
}

class AnotherService(){
    void anotherServiceMethod(){
    \\something
    }
}

在这种情况下,我得到 无法在空对象上调用“anotherServiceMethod”。 有什么方法可以测试这种类型的控制器吗?在另一个服务中注入服务是一种好方法吗?

【问题讨论】:

    标签: unit-testing grails grails-3.0.10


    【解决方案1】:

    将服务注入另一个服务是一个很好的方法,没有错。

    要使这个测试有效,有几种方法。

    推荐 - 单元测试应该只测试单个类的行为,如果你需要测试完整的功能,集成/功能规范会更好。在这种情况下,您执行控制器的方法,但所有其他被调用的类都是您预测返回什么值的模拟。然后为 MyService 和 AnotherService 创建单独的测试。在这种情况下,您的测试可能如下所示:

    @TestFor(MyController)
    class MyControllerSpec extends Specification {
        void "test something"(){
            given:
                MyService myService = Mock()
                controller.myService = myService
            when:
                controller.method1();
            then:
                1 * myService.serviceMethod() >> someResult
                //something
        }
    }
    

    这个测试确保 serviceMethod() 被调用并且你强制它返回你对这个规范的期望。如果在其他情况下(抛出异常,如果/否则你想确保 serviceMethod() 没有被调用,你可以使用0 * myService.serviceMethod()

    不推荐:如果您坚持在本规范中调用服务方法,您可以创建 AnotherService 的模拟并将其设置在控制器中可用的服务上。比如:

    AnotherService anotherService = Mock()
    controller.myService.anotherService = anotherService
    ...
    then:
    1 * anotherService.callAnotherMethod()
    

    也许使用@Mock([MyService, AnotherService]) 也可以,但我没有测试它。我们使用集成测试来测试集成 - 一切都为您注入,您可以在普通类上工作。

    【讨论】:

    • 这意味着我不需要真正深入调用方法。我可以提供我对函数调用的期望,然后测试该方法吗?
    • 是否有可用的文档,因为我不知道 0* ... 1* 表示法。?
    • 是的,Grails 使用 Spock 框架。只需阅读以下文档:spockframework.github.io/spock/docs/1.0/index.html 和 Grails 应用程序的单元测试部分,用于特定于 Grails 工件的测试
    • 是的,你不需要深入调用方法——这是单元测试的主要思想只是单个类和模拟其他类,你只需说出你期望调用的方法对于这些方法的不同结果,哪些类以及您的类的行为方式。
    • 现在我可以模拟服务的功能,但不能模拟控制器的功能。假设我正在测试的控制器方法调用另一个控制器方法,当我使用“controller.secondMethod”模拟该方法时它不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 2015-01-07
    • 2013-10-17
    • 1970-01-01
    相关资源
    最近更新 更多