#java #spring #spring-boot #unit-testing
#Ява #весна #пружинный ботинок #модульное тестирование
Вопрос:
В проекте Spring Boot мы получаем доступ к нашим неуправляемым классам DAO с помощью статического метода:
MyDao myDao = DaoProvider.getMyDao();
Мы используем это в весенних управляемых @Service
классах:
@Service public class MyService { public void foo() { MyDao myDao = DaoProvider.getMyDao(); myDao.bar(); .... } }
Это затрудняет написание модульных тестов. Статические насмешки-это не вариант, потому что они замедляют наш конвейер сборки.
Мы предпочли бы иметь решение с @Autowired
зависимостью от конструктора или с какой-либо конфигурацией, которая решает, какой класс вводить:
@Service public class MyService { @Autowired MyDao myDao; public void foo() { myDao.bar(); .... } }
Очевидно, кто-то должен сказать Spring, какой класс вводить, потому MyDao
что нет управляемого компонента Spring. Есть ли способ сделать это?:
@Configuration public class NonManagedSpringInjectionConfiguration { @Bean MyDao getMyDao() { return DaoProvider.getMyDao(); } }
Комментарии:
1. Что вы имеете в виду под
someone has to tell Spring what class to inject
этим ? Spring автоматически вводит все, если @Autowire, @Service и @Bean используются правильно2. MyDao-это не управляемый боб с пружиной. Так что Весна не сможет обнаружить его из коробки. Спасибо за подсказку, я отредактировал вопрос.
3. Вы решили свою проблему?
4. Да, спасибо, что спросили. Я не знал, что вы можете в значительной степени зарегистрировать любой класс в качестве компонента, как описано в варианте 2 в принятом ответе.
Ответ №1:
Вариант 1
Если вы не хотите превращать свой MyDao
компонент в управляемый пружиной компонент, ваш более простой и, вероятно, лучший вариант-вместо этого создать MyService
управляемый пружиной компонент программно, а не полагаться на @Service
аннотации. Во-первых, просто удалите @Service
из MyService
и настройте его конструктор так, чтобы он принимал MyDao
:
public class MyService { MyDao myDao; public MyService(MyDao myDao) { this.myDao = myDao; } public void foo() { myDao.bar(); .... } }
И теперь вам просто нужно зарегистрировать MyService
компонент, используемый @Bean
в классе конфигурации, следующим образом:
@Configuration public class WhateverConfiguration { @Bean MyService myService() { return new MyService(DaoProvider.getMyDao()); } }
Вариант 2
Если вместо этого есть возможность создать MyDao
управляемый пружиной боб, просто сохраните NonManagedSpringInjectionConfiguration
его как есть:
@Configuration public class NonManagedSpringInjectionConfiguration { @Bean MyDao getMyDao() { return DaoProvider.getMyDao(); } }
Но тогда полагайтесь на инъекцию конструктора, а не на @Autowired
. Это MyService
облегчает модульное тестирование, а также явно определяет, что MyDao
является обязательным для MyService
правильной работы. В этом случае вы бы сохранили @Service
и полагались на Spring для его создания:
@Service public class MyService { MyDao myDao; public MyService(MyDao myDao) { this.myDao = myDao; } public void foo() { myDao.bar(); .... } }
Ответ №2:
Вам просто нужно указать профиль, например :
@Configuration public class NonManagedSpringInjectionConfiguration { @Bean @Profile("dev") MyDao getMyDao() { return DaoProvider.getMyDao(); } }