Я не могу передать поле, прочитав файл application-test.properties из теста в тестовый метод.
@RunWith(SpringRunner.class)
@TestPropertySource("classpath:application-test.properties")
public class ReportImplTest {
@Mock
private Dependencies dependencies;
@InjectMocks
private ReportImplTest underTest;
@Test
public void testgetReports() {
List<String> reps= underTest.getReports(anyString());
}
}
Вот фактический класс издеваемого метода
@Component
public class ReportImpl {
@Value("${REP_PROPNAME}")
String reppropname;
public List<String> getReports(String rep){
return staticUtilityclass.process(staticUtilityclass.transform(reppropname,"Reports"));
}
}
reppropname принимает значение null в методе getReports. Тест выполняется в контексте теста, где класс ReportImpl будет в контексте приложения. Есть ли способ узнать стоимость reppropname.
Пробовал использовать @ContextConfiguration (@ContextConfiguration(classes = {ApplicaitonBootStarter.class)}
он работает, но загружает все компоненты и зависимости.
Есть ли другой способ получить имя реппропа?
@chrylis вы имеете в виду вместо инъекции поля с использованием аннотации значений? не могли бы вы пролить больше света
Вы можете поместить @Value в параметр метода, и Spring с радостью настроит конструкторы autowire.
@chrylis не работает, так как reppropname используется в статическом методе.
Тогда показанный вами класс не будет компилироваться. (Ответ, конечно, «передать как параметр».)
Ваш тест практически бесполезен, поскольку ничего не делает. Он загружает конфигурацию пружины и после этого игнорирует ее. С обычным приложением Spring @Mock и @InjectMocks также будут null, и ваш тест провалится (тот факт, что он работает, заставляет меня задуматься, не используете ли вы Spring Boot). ReportImpl не управляется Spring, поскольку @InjectMocks создает новый экземпляр вне Spring, и поэтому @Value не будет обрабатываться. Так что просто вставьте экземпляр из контекста приложения. Да, он загрузит все, но только один раз и кеширует все для последующих тестов.




Причина, по которой значение здесь не вводится, заключается в том, что вы не предоставляете конфигурацию своему тестовому классу. Spring просто не знает, как построить ваш bean-компонент.
Итак, как вы упомянули, вы должны аннотировать тестовый класс с помощью @ContextConfiguration. Если вы не хотите создавать весь контекст со всеми bean-компонентами, вы можете создать тестовую конфигурацию и предоставить там только необходимые bean-компоненты.
@Configuration //can be as well annotated with @TestConfiguration
@ComponentScan("package.to.scan")
public class TestConfiguration {
}
А теперь предоставьте этот класс вашему тесту
@RunWith(SpringRunner.class)
@TestPropertySource("classpath:application-test.properties")
@ContextConfiguration(classes = TestConfiguration.class)
public class ReportImplTest {
........
}
Но есть еще один момент. Предполагая, что у вас есть метод @Before, который выполняет MockitAnnotations.initMocks(this);, тестируемый объект по-прежнему объявлен только с @InjectMocks. Что это значит? Это означает, что если вы не инициализируете этот объект самостоятельно, mockito позаботится об этом и инициализируется с использованием доступного конструктора, и в этом случае spring не будет вводить аннотированное поле @Value. Что вам нужно сделать, так это аннотировать тестируемый объект с помощью @Autowired, чтобы Spring инициализировал его до того, как mockito попытается о нем позаботиться:
@InjectMocks
@Autowired
private ReportImplTest underTest;
Это было бы намного проще, если бы вместо этого вы использовали внедрение конструктора; вам вообще не понадобится Spring для теста.