단위 테스트 중 스프링 채우기 @값
내 프로그램에서 양식의 유효성을 검사하는 데 사용되는 간단한 콩에 대한 단위 테스트를 작성하려고 한다.을 @Component
를 사용하여 초기화된 클래스 변수를 가지고 있다.
@Value("${this.property.value}") private String thisProperty;
나는 이 수업에서 검증 방법에 대한 단위 테스트를 쓰고 싶은데 가능하다면 속성 파일을 활용하지 않고 작성했으면 좋겠어.이것의 배경은, 만약 내가 속성 파일에서 뽑고 있는 값이 바뀌게 된다면, 나는 그것이 나의 테스트 케이스에 영향을 주지 않기를 바란다.내 테스트 케이스는 값을 검증하는 코드를 테스트하는 것이지 값 자체를 테스트하는 것이 아니다.
테스트 클래스 내에 Java 코드를 사용하여 Java 클래스를 초기화하고 해당 클래스 내에 Spring @Value 속성을 채운 다음 테스트에 사용할 수 있는 방법이 있는가?
이 How To가 가까이 있는 것처럼 보이지만 여전히 속성 파일을 사용한다.나는 그것이 모두 자바코드가 되기를 바란다.
가능하다면 스프링 컨텍스트 없이 그 테스트들을 쓰려고 노력할 것이다.봄 없이 테스트에서 이 클래스를 만들면 해당 필드를 완전히 제어할 수 있다.
설정하기@value
스프링스를 사용할 수 있는 필드 - 개인 필드를 설정하는 방법이 있다.
@JavDoc: 반사 참조TestUtils.setField(java.lang).객체, java.lang.문자열, java.lang.객체)
Spring 4.1 이후 당신은 단지 코드로 속성 값을 설정 할 수 있었다.org.springframework.test.context.TestPropertySource
Unit Tests 클래스 레벨에 대한 주석.종속 콩 인스턴스에 속성을 주입하는 경우에도 이 방법을 사용할 수 있다.
예를 들면
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = FooTest.Config.class)
@TestPropertySource(properties = {
"some.bar.value=testValue",
})
public class FooTest {
@Value("${some.bar.value}")
String bar;
@Test
public void testValueSetup() {
assertEquals("testValue", bar);
}
@Configuration
static class Config {
@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
}
}
참고: 다음이 필요한 경우org.springframework.context.support.PropertySourcesPlaceholderConfigurer
봄의 맥락에서
24-08-2017 편집: SpringBoot 1.4.0 이상을 사용하는 경우 및 주석을 사용하여 테스트를 초기화할 수 있다.자세한 내용은 여기를 참조하십시오.
SpringBoot의 경우 다음 코드가 있음
@SpringBootTest
@SpringBootConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(properties = {
"some.bar.value=testValue",
})
public class FooTest {
@Value("${some.bar.value}")
String bar;
@Test
public void testValueSetup() {
assertEquals("testValue", bar);
}
}
개인 필드를 남용하지 마십시오. 반영하여 설정/설정
여기서 몇 가지 대답에서 그렇게 한 것처럼 반성을 하는 것은 우리가 피할 수 있는 것이다.
여러 가지 단점을 제시하면서도 여기에 작은 가치를 가져다 준다.
- 런타임에만 반영 문제를 탐지함(예: 더 이상 존재하지 않는 필드)
- 우리는 캡슐화를 원하지만 가시적이어야 할 의존성을 숨기고 클래스를 더 불투명하고 테스트할 수 없게 만드는 불투명한 클래스는 원하지 않는다.
- 그것은 나쁜 디자인을 장려한다.오늘 당신은 선언한다.
@Value String field
내일 당신은 선언할 수 있다.5
, 또는10
그 수업의 그것들 중에서 그리고 당신은 심지어 당신이 수업의 디자인을 줄인다는 것을 똑바로 알지 못할 수도 있다.이러한 필드(예: 생성자)를 설정하는 보다 가시적인 접근방식으로, 이 모든 필드를 추가하기 전에 두 번 생각할 것이며, 아마도 다른 클래스로 캡슐화하여 사용할 것이다.@ConfigurationProperties
.
단일 클래스와 통합 모두를 테스트할 수 있도록 지원
스프링 구성 요소 클래스에 대한 일반 단위 테스트(실행 중인 스프링 컨테이너가 없는 테스트)와 통합 테스트를 모두 작성할 수 있으려면 이 클래스를 스프링과 함께 사용하거나 사용하지 않고 사용할 수 있도록 만들어야 한다.
필요하지 않은 경우 장치 테스트에서 용기를 실행하는 것은 로컬 빌드를 느리게 하는 나쁜 관행이다. 즉, 그렇게 하는 것을 원하지 않는다.
여기에서는 어떤 대답도 이러한 차이를 보이지 않는 것 같아서 그들은 체계적으로 달리는 용기에 의존하고 있기 때문에 나는 이 대답을 추가했다.
그러므로 나는 당신이 클래스 내부로 정의된 이 속성을 옮겨야 한다고 생각한다.
@Component
public class Foo{
@Value("${property.value}") private String property;
//...
}
Spring에 의해 주입될 생성자 파라미터로:
@Component
public class Foo{
private String property;
public Foo(@Value("${property.value}") String property){
this.property = property;
}
//...
}
단위 테스트 예
인스턴스화할 수 있음Foo
스프링 없이 다음 값을 주입하십시오.property
덕택시자자 덕후:
public class FooTest{
Foo foo = new Foo("dummyValue");
@Test
public void doThat(){
...
}
}
통합 테스트 예제
부트로의 스프링 할 수 있다.properties
의 탓으로 돌리다.@SpringBootTest
:
@SpringBootTest(properties="property.value=dummyValue")
public class FooTest{
@Autowired
Foo foo;
@Test
public void doThat(){
...
}
}
당신은 대안으로 사용할 수 있다.@TestPropertySource
그러나 다음과 같은 주석을 추가한다.
@SpringBootTest
@TestPropertySource(properties="property.value=dummyValue")
public class FooTest{ ...}
스프링이 있으면(스프링 부츠 없이) 조금 더 복잡할 텐데, 스프링 부츠가 없는 스프링은 오랫동안 사용하지 않았기 때문에 나는 바보 같은 말을 하는 것을 선호하지 않는다.
참고로: 만약 당신이 많은 것을 가지고 있다면@Value
설정할 필드, 주석을 사용하여 클래스로 추출@ConfigurationProperties
우리는 너무 많은 논쟁을 가진 건설자를 원하지 않기 때문에 더 목적적합하다.
원하는 경우, 봄 컨텍스트 내에서 테스트를 실행하고 봄 구성 클래스 내에서 필요한 속성을 설정할 수 있다.JUnit을 사용할 경우 Spring을 사용하십시오.JUnit4ClassRunner와 같은 테스트 전용 구성 클래스를 정의하십시오.
테스트 대상 클래스:
@Component
public SomeClass {
@Autowired
private SomeDependency someDependency;
@Value("${someProperty}")
private String someProperty;
}
테스트 클래스:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SomeClassTestsConfig.class)
public class SomeClassTests {
@Autowired
private SomeClass someClass;
@Autowired
private SomeDependency someDependency;
@Before
public void setup() {
Mockito.reset(someDependency);
@Test
public void someTest() { ... }
}
이 테스트의 구성 클래스:
@Configuration
public class SomeClassTestsConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer properties() throws Exception {
final PropertySourcesPlaceholderConfigurer pspc = new PropertySourcesPlaceholderConfigurer();
Properties properties = new Properties();
properties.setProperty("someProperty", "testValue");
pspc.setProperties(properties);
return pspc;
}
@Bean
public SomeClass getSomeClass() {
return new SomeClass();
}
@Bean
public SomeDependency getSomeDependency() {
// Mockito used here for mocking dependency
return Mockito.mock(SomeDependency.class);
}
}
그렇다고 해서, 나는 이 방법을 추천하지 않을 것이다, 나는 참고하기 위해 여기에 그것을 추가했을 뿐이다.내 생각에 훨씬 더 좋은 방법은 모키토 러너를 이용하는 것이다.그런 경우라면 스프링 안에서 테스트를 전혀 하지 않는 것이 훨씬 명확하고 간단하다.
이 방법은 효과가 있는 것 같지만, 약간 장황하긴 하지만(아직 좀 더 짧은 것을 원해):
@BeforeClass
public static void beforeClass() {
System.setProperty("some.property", "<value>");
}
// Optionally:
@AfterClass
public static void afterClass() {
System.clearProperty("some.property");
}
구성에서 PropertyPlaceholderConfigurr를 추가하는 것이 나에게 효과가 있다.
@Configuration
@ComponentScan
@EnableJpaRepositories
@EnableTransactionManagement
public class TestConfiguration {
@Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
builder.setType(EmbeddedDatabaseType.DERBY);
return builder.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPackagesToScan(new String[] { "com.test.model" });
// Use hibernate
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
return entityManagerFactoryBean;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "false");
properties.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
properties.put("hibernate.hbm2ddl.auto", "update");
return properties;
}
@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManagerFactory().getObject()
);
return transactionManager;
}
@Bean
PropertyPlaceholderConfigurer propConfig() {
PropertyPlaceholderConfigurer placeholderConfigurer = new PropertyPlaceholderConfigurer();
placeholderConfigurer.setLocation(new ClassPathResource("application_test.properties"));
return placeholderConfigurer;
}
}
그리고 시험시간에
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
public class DataServiceTest {
@Autowired
private DataService dataService;
@Autowired
private DataRepository dataRepository;
@Value("${Api.url}")
private String baseUrl;
@Test
public void testUpdateData() {
List<Data> datas = (List<Data>) dataRepository.findAll();
assertTrue(datas.isEmpty());
dataService.updateDatas();
datas = (List<Data>) dataRepository.findAll();
assertFalse(datas.isEmpty());
}
}
@ExtendWith(SpringExtension.class) // @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class)
그게 도움이 될 수 있기를.핵심은 ConfigDataApplicationContextInitializer가 모든 소품 데이터 가져오기입니다.
꽤 오래된 질문이고, 그 당시에는 선택사항이었는지는 잘 모르겠지만, 이것이 내가 항상 의존성을 선호하는 이유야.값보다 생성자에 의한 주입.
네 수업은 이렇게 생겼을지도 몰라
class ExampleClass{
@Autowired
private Dog dog;
@Value("${this.property.value}")
private String thisProperty;
...other stuff...
}
다음 항목으로 변경 가능:
class ExampleClass{
private Dog dog;
private String thisProperty;
//optionally @Autowire
public ExampleClass(final Dog dog, @Value("${this.property.value}") final String thisProperty){
this.dog = dog;
this.thisProperty = thisProperty;
}
...other stuff...
}
이 구현으로 스프링은 자동으로 주입해야 할 것을 알게 되겠지만, 유닛 테스트의 경우 필요한 것은 무엇이든 할 수 있다.예를 들어, 모든 종속성을 봄과 함께 자동화하고 생성자를 통해 수동으로 주입하여 "ExampleClass" 인스턴스를 생성하거나, 테스트 속성 파일이 있는 스프링만 사용하거나, 스프링을 전혀 사용하지 않고 모든 개체를 직접 생성하십시오.
스프링부트에서 2.4.1 나는 방금 주석을 추가했다.@SpringBootTest
내 시험에서, 그리고 분명히, 정해진.spring.profiles.active = test
나의src/test/resources/application.yml
나는 사용하고 있다.@ExtendWith({SpringExtension.class})
그리고@ContextConfiguration(classes = {RabbitMQ.class, GenericMapToObject.class, ModelMapper.class, StringUtils.class})
외부와의 교감을 위해.
Spring Boot는 자동으로 많은 작업을 수행하지만 우리가 주석을 사용할 때@SpringBootTest
우리는 모든 것이 스프링 부츠에 의해 자동으로 해결될 것이라고 생각한다.
문서화는 많지만, 최소는 엔진 하나를 선택하는 것이다.@RunWith(SpringRunner.class)
() 및 구성을 로드할 컨텍스트를 생성할 클래스를 표시하십시오(resources/applicationl.properties
).
간단한 방법으로 엔진과 컨텍스트가 필요:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyClassTest .class)
public class MyClassTest {
@Value("${my.property}")
private String myProperty;
@Test
public void checkMyProperty(){
Assert.assertNotNull(my.property);
}
}
물론, 스프링 부트 문서를 보면 그렇게 할 수 있는 수천 가지 방법을 찾을 수 있을 것이다.
참조URL: https://stackoverflow.com/questions/17353327/populating-spring-value-during-unit-test
'Programing' 카테고리의 다른 글
다른 Vue 플러그인의 Vue 플러그인 사용 (0) | 2022.04.24 |
---|---|
vue 구성 요소에 업로드된 이미지별로 이미지를 표시하는 방법 (0) | 2022.04.24 |
Java에서 파일을 복사하는 표준 간결한 방법? (0) | 2022.04.24 |
Axios 인터셉터 토큰 헤더가 구성에는 있지만 요청 헤더에는 없음 (0) | 2022.04.23 |
Vue.js의 지시어를 사용하여 숫자 값만 수락하는 입력 필드 (0) | 2022.04.23 |