In unit test cases of controllers i'm only able to inject the services that are used in the corresponding controller.But if say one service in controller injects another service then my test cases gets failed i.e. can not invoke service method on null object.
@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
}
}
in this case, I'm getting can not invoke "anotherServiceMethod" on null object. is there any way to test this type of controller? and is it a good approach to inject a service in another service?
It is a good approach to inject serice into another service, nothing wrong with that.
To make this test working there are few approaches.
Recommended - unit test should test behaviour of only single class, if you need to test full functionality, integration/functional spec is better to do that. In such case, you execute methods of your controller, but all other classes which are called are mocks on which you predict what values are returned. Then you create separate tests for MyService and AnotherService. In such case, your test could look like:
this test ensures, that serviceMethod() is called and you force it to return something what you expect for this spec. If in other case (exception thrown, if/else you want to be sure that serviceMethod() is not called, you can use
0 * myService.serviceMethod()Not recommended: If you insist that service method should be called in this spec, you can create mock of
AnotherServiceand set it on the service which is available in controller. Something like:Maybe also using
@Mock([MyService, AnotherService])will work, but I didn't test it. We test integrations with integration tests - there everything is injected for you and you work on normal classes.