如何测试grails 3控制器与其他服务注入其中的服务?

YoY*_*ngh 1 grails unit-testing grails-3.0.10

在控制器的单元测试用例中,我只能注入相应控制器中使用的服务.但是如果控制器中的一个服务注入另一个服务,那么我的测试用例就会失败,即无法调用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
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我无法在null对象上调用"anotherServiceMethod".有没有办法测试这种类型的控制器?在其他服务中注入服务是一种好方法吗?

dro*_*ggo 8

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

为了使这个测试工作,几乎没有办法.

推荐 - 单元测试应该只测试单个类的行为,如果需要测试全部功能,那么集成/功能规范更好.在这种情况下,您执行控制器的方法,但所有其他被调用的类都是模拟,您可以在其上预测返回的值.然后为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
    }
}
Run Code Online (Sandbox Code Playgroud)

此测试确保调用serviceMethod()并强制它返回您对此规范所期望的内容.如果在其他情况下(抛出异常,如果/你想确定没有调用serviceMethod(),你可以使用0 * myService.serviceMethod()

不推荐:如果您坚持在本规范中调用服务方法AnotherService,则可以在控制器中可用的服务上创建模拟并设置它.就像是:

AnotherService anotherService = Mock()
controller.myService.anotherService = anotherService
...
then:
1 * anotherService.callAnotherMethod()
Run Code Online (Sandbox Code Playgroud)

也许还可以使用@Mock([MyService, AnotherService])将工作,但我没有测试它.我们测试集成测试的集成 - 所有内容都是为您注入的,您可以在正常的类上工作.