如何使用注入了其他服务的服务来测试 grails 3 控制器?
how to test grails 3 controller with services that have another services inject into them?
在控制器的单元测试用例中,我只能注入相应 controller.But 中使用的服务,如果说控制器中的一个服务注入了另一个服务,那么我的测试用例就会失败,即无法调用空对象上的服务方法。
@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"。
有什么方法可以测试这种类型的控制器吗?在另一个服务中注入服务是一种好方法吗?
将服务注入另一个服务是一种很好的方法,这没有错。
要使此测试有效,有几种方法。
推荐 - 单元测试应该只测试单个 class 的行为,如果您需要测试全部功能,integration/functional 规范更适合这样做。在这种情况下,您执行控制器的方法,但所有其他被调用的 classes 都是模拟,您可以预测哪些值是 returned。然后为 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() 并且您强制它 return 满足您对该规范的期望。如果在其他情况下(抛出异常,if/else 你想确保 serviceMethod() 没有被调用,你可以使用 0 * myService.serviceMethod()
不推荐:如果您坚持在本规范中调用服务方法,您可以创建 AnotherService
的模拟并将其设置在控制器中可用的服务上。类似于:
AnotherService anotherService = Mock()
controller.myService.anotherService = anotherService
...
then:
1 * anotherService.callAnotherMethod()
也许也可以使用 @Mock([MyService, AnotherService])
,但我没有测试过。我们通过集成测试来测试集成 - 一切都为您注入,您可以正常工作 classes.
在控制器的单元测试用例中,我只能注入相应 controller.But 中使用的服务,如果说控制器中的一个服务注入了另一个服务,那么我的测试用例就会失败,即无法调用空对象上的服务方法。
@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"。 有什么方法可以测试这种类型的控制器吗?在另一个服务中注入服务是一种好方法吗?
将服务注入另一个服务是一种很好的方法,这没有错。
要使此测试有效,有几种方法。
推荐 - 单元测试应该只测试单个 class 的行为,如果您需要测试全部功能,integration/functional 规范更适合这样做。在这种情况下,您执行控制器的方法,但所有其他被调用的 classes 都是模拟,您可以预测哪些值是 returned。然后为 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() 并且您强制它 return 满足您对该规范的期望。如果在其他情况下(抛出异常,if/else 你想确保 serviceMethod() 没有被调用,你可以使用 0 * myService.serviceMethod()
不推荐:如果您坚持在本规范中调用服务方法,您可以创建 AnotherService
的模拟并将其设置在控制器中可用的服务上。类似于:
AnotherService anotherService = Mock()
controller.myService.anotherService = anotherService
...
then:
1 * anotherService.callAnotherMethod()
也许也可以使用 @Mock([MyService, AnotherService])
,但我没有测试过。我们通过集成测试来测试集成 - 一切都为您注入,您可以正常工作 classes.