Как проверить Grails 3 контроллера с сервисами, которые имеют другие сервисы в них?
В случаях модульного тестирования контроллеров я могу вводить только те службы, которые используются в соответствующем контроллере. Но если, скажем, одна служба в контроллере внедряет другую службу, мои тестовые примеры терпят неудачу, т.е. не могут вызвать метод службы для нулевого объекта.
@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" для нулевого объекта. Есть ли способ проверить этот тип контроллера? и это хороший подход для внедрения службы в другой сервис?
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])
будет работать, но я не проверял это. Мы тестируем интеграцию с интеграционными тестами - там все для вас вводится и вы работаете на обычных классах.