#spring #kotlin
Вопрос:
Язык программирования не имеет значения для этого вопроса: Котлин и Java в порядке.
В моем проекте у меня есть наследование классов обслуживания. При написании тестов с помощью Mockito выясняется, что @MockBean
с дочерними классами это не работает, если я также не аннотирую родительские классы @Service
.
Мне хотелось бы знать, проблематично ли весной иметь аннотации к дочерним и родительским классам @Service
.
Какие-нибудь проблемы с этим?:
@Service
abstract class BaseCrudService { ... }
@Transactional
@Service
class PersonService(...) : BaseCrudService { ... }
Обратите внимание, что BaseCrudService
и то, и PersonService
другое снабжено комментариями @Service
Обновить
Отвечая на вопрос М. Дейна, вот полный пример:
Базовый класс:
abstract class BaseCrudService {
fun foo() {
println("BaseCrudService#foo")
}
}
Детский класс:
@Service
class PersonService : BaseCrudService() {
fun bar() {
println("PersonService#bar")
}
}
Контроллер, использующий класс Service/child:
@Controller
class MyController(val personService: PersonService) {
fun myMethod() {
println("MyController#myMethod")
personService.foo()
personService.bar()
}
}
Тест:
@WebMvcTest(MyController::class)
class MyControllerTest {
@MockBean
lateinit var personService: PersonService
@Autowired
lateinit var myController: MyController
@Test
fun testMyMethod() {
myController.myMethod()
}
}
Without annotating the base class with @Service
the test output is:
MyController#myMethod
BaseCrudService#foo
Как вы можете видеть, метод дочернего класса подвергается насмешкам (без вывода), но вызывается метод базового класса (имеет вывод).
С аннотацией @Service abstract class BaseCrudService { ... }
вывод будет:
MyController#myMethod
Методы дочернего и родительского классов подвергаются насмешкам.
При аннотировании как родительского, так и дочернего класса с помощью @Service я получаю ожидаемое поведение. Но мне интересно, есть ли какие-либо проблемы с аннотацией обоих классов с помощью @Service для Spring?
Обновление 2
В предыдущем примере проблема BaseCrudService#foo
является окончательной. В Kotlin методы являются общедоступными, окончательными по умолчанию, см. Эту статью.
Mockito не выводил никаких предупреждений (возможно, из-за настроек журнала). Он не может имитировать окончательные методы, см. Эту статью. После взлома BaseCrudService#foo
open
я могу безопасно удалить @Service
из BaseCrudService
. @Service
родительскому классу волшебным образом позволяет Mockito издеваться над конечным методом. Поэтому мне нужно найти способ издеваться над окончательным методом (это не входит в вопрос).
Но независимо от того, что касается насмешки, вопрос остается открытым.
В статье, где должна храниться аннотация Spring @Service? обсуждается другой способ: аннотируется только (абстрактный) родительский класс @Service
, но не дочерний класс.
Комментарии:
1. Описание вашей проблемы не имеет смысла. Почему бы это не сработало, с какой проблемой вы столкнулись?
Ответ №1:
@Service
abstract class BaseCrudService { ... }
Здесь вы объявили свой класс абстрактным. У Spring не будет способа создать экземпляр, как вы проинструктировали его сделать с @Service
Комментарии:
1. Спасибо! Так что Весна может спокойно игнорировать это? Никаких проблем с производительностью или проблем с инструментами?