Mockito와 함께 봄의 자동 전원 @Value 필드를 조롱하려면 어떻게 해야 하나요?
Spring 3.1.4를 사용하고 있습니다.릴리즈 및 모키토 1.9.5.봄 수업에는 다음과 같은 것이 있습니다.
@Value("#{myProps['default.url']}")
private String defaultUrl;
@Value("#{myProps['default.password']}")
private String defaultrPassword;
// ...
JUnit 테스트에서 다음과 같이 셋업하고 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:test-context.xml" })
public class MyTest
{
합니다. "defaultUrl" 필드입니다.하다 "defaultUrl"로 지정합니다. 명시적인 예: "setter" 메서드)는.setDefaultUrl
테스트 목적으로만 만들고 싶지는 않습니다.
이 경우 해당 필드의 값을 어떻게 조롱할 수 있습니까?
할 수 .ReflectionTestUtils.setField
코드를 변경하지 않도록 합니다.
Michau Stochmal의 코멘트는 다음과 같은 예를 제시합니다.
ReflectionTestUtils.setField(bean, "fieldName", "value");
를bean
방법을 지정합니다.
이 방법은 매우 사용하기 쉽기 때문에 필요 없을 수도 있지만 자세한 내용은 이 튜토리얼을 참조하십시오.
갱신하다
Spring 4.2가 도입된 이후.RC1은 이제 클래스의 인스턴스를 제공하지 않고도 정적 필드를 설정할 수 있습니다.문서의 이 부분과 이 커밋을 참조하십시오.
@Value 필드를 조롱하는 방법을 항상 잊어버리기 때문에 이 SO 포스트에 제 자신을 구글로 검색한 것은 이번이 세 번째입니다.수용된 답변은 맞지만, "setField" 호출을 올바르게 하기 위해서는 항상 시간이 필요합니다.그래서 적어도 제 자신에게는 여기에 샘플 스니펫을 붙여 넣습니다.
프로덕션 클래스:
@Value("#{myProps[‘some.default.url']}")
private String defaultUrl;
테스트 클래스:
import org.springframework.test.util.ReflectionTestUtils;
ReflectionTestUtils.setField(instanceUnderTest, "defaultUrl", "http://foo");
// Note: Don't use MyClassUnderTest.class, use the instance you are testing itself
// Note: Don't use the referenced string "#{myProps[‘some.default.url']}",
// but simply the FIELDs name ("defaultUrl")
다음 매직 스프링 테스트 주석을 사용할 수 있습니다.
@TestPropertySource(properties = { "my.spring.property=20" })
org.springframework.test.disc를 참조하십시오.TestPropertySource
예를 들어 테스트클래스는 다음과 같습니다.
@ContextConfiguration(classes = { MyTestClass.Config.class })
@TestPropertySource(properties = { "my.spring.property=20" })
public class MyTestClass {
public static class Config {
@Bean
MyClass getMyClass() {
return new MyClass ();
}
}
@Resource
private MyClass myClass ;
@Test
public void myTest() {
...
다음은 속성을 가진 클래스입니다.
@Component
public class MyClass {
@Value("${my.spring.property}")
private int mySpringProperty;
...
저는 이와 된 해결책을. 즉, ''을 하는 것입니다.@Value
로서 constructor를 constructor에 대한 parameter로서 constructor 합니다.ReflectionTestUtils
이것 대신:
public class Foo {
@Value("${foo}")
private String foo;
}
그리고.
public class FooTest {
@InjectMocks
private Foo foo;
@Before
public void setUp() {
ReflectionTestUtils.setField(Foo.class, "foo", "foo");
}
@Test
public void testFoo() {
// stuff
}
}
다음을 수행합니다.
public class Foo {
private String foo;
public Foo(@Value("${foo}") String foo) {
this.foo = foo;
}
}
그리고.
public class FooTest {
private Foo foo;
@Before
public void setUp() {
foo = new Foo("foo");
}
@Test
public void testFoo() {
// stuff
}
}
이 접근법의 장점: 1) 의존관계 컨테이너 없이 Foo 클래스를 인스턴스화할 수 있으며(그냥 컨스트럭터), 2) 구현 세부사항에 테스트를 결합하지 않습니다(반영에 의해 필드 이름이 연결되므로 필드 이름이 변경될 경우 문제가 발생할 수 있습니다).
테스트 클래스에 속성 구성을 모의할 수도 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:test-context.xml" })
public class MyTest
{
@Configuration
public static class MockConfig{
@Bean
public Properties myProps(){
Properties properties = new Properties();
properties.setProperty("default.url", "myUrl");
properties.setProperty("property.value2", "value2");
return properties;
}
}
@Value("#{myProps['default.url']}")
private String defaultUrl;
@Test
public void testValue(){
Assert.assertEquals("myUrl", defaultUrl);
}
}
아래 코드를 사용했는데, 작동했습니다.
@InjectMocks
private ClassABC classABC;
@Before
public void setUp() {
ReflectionTestUtils.setField(classABC, "constantFromConfigFile", 3);
}
참고 자료: https://www.jeejava.com/mock-an-autowired-value-field-in-spring-with-junit-mockito/
또, 클래스에는 명시적인 「setter」메서드(setDefaultUrl 등)가 없기 때문에, 테스트의 목적으로만 작성하는 것은 원하지 않습니다.
이 문제를 해결하는 한 가지 방법은 클래스를 테스트 및 스프링 주입에 사용할 수 있는 생성자 주입을 사용하도록 변경하는 것입니다.반사는 없습니다:)
따라서 컨스트럭터를 사용하여 임의의 문자열을 전달할 수 있습니다.
class MySpringClass {
private final String defaultUrl;
private final String defaultrPassword;
public MySpringClass (
@Value("#{myProps['default.url']}") String defaultUrl,
@Value("#{myProps['default.password']}") String defaultrPassword) {
this.defaultUrl = defaultUrl;
this.defaultrPassword= defaultrPassword;
}
}
그리고 테스트에서는 이것을 사용해 주세요.
MySpringClass MySpringClass = new MySpringClass("anyUrl", "anyPassword");
가능하면 테스트 클래스에서 액세스할 수 있도록 필드 가시성을 패키지 보호로 설정합니다.나는 Guava의 @VisibleForTesting 주석을 사용하여 기록한다(다음 사람이 왜 비공개로 되어 있지 않은지 궁금할 경우).이렇게 하면 필드의 문자열 이름에 의존할 필요가 없고 모든 것이 안전하게 유지됩니다.
학교에서 배운 표준 캡슐화 관행에 어긋난다는 것을 알고 있습니다.하지만 팀 내에서 이런 방향으로 가는 것에 대한 합의가 이루어지자마자, 저는 그것이 가장 실용적인 해결책이라는 것을 알게 되었습니다.
또 다른 방법은@SpringBootTest
주석properties
들판.
여기서 덮어씁니다.example.firstProperty
속성:
@SpringBootTest(properties = { "example.firstProperty=annotation" })
public class SpringBootPropertySourceResolverIntegrationTest {
@Autowired private PropertySourceResolver propertySourceResolver;
@Test
public void shouldSpringBootTestAnnotation_overridePropertyValues() {
String firstProperty = propertySourceResolver.getFirstProperty();
String secondProperty = propertySourceResolver.getSecondProperty();
Assert.assertEquals("annotation", firstProperty);
Assert.assertEquals("defaultSecond", secondProperty);
}
}
보시다시피 하나의 속성만 덮어씁니다.에 기재되어 있지 않은 속성@SpringBootTest
손대지 않다따라서 테스트를 위해 특정 속성만 덮어쓸 필요가 있는 경우 이는 훌륭한 솔루션입니다.
단일 속성의 경우 대괄호 없이 쓸 수 있습니다.
@SpringBootTest(properties = "example.firstProperty=annotation")
답변: https://www.baeldung.com/spring-tests-override-properties#springBootTest
또한 Dherik answer(https://stackoverflow.com/a/52955459/1673775)에서와 같이 가능한 한 속성을 파라미터로 전달하여 유닛 테스트에서 쉽게 속성을 모킹할 수 있도록 하는 것이 좋습니다.
그러나 통합 테스트에서는 개체를 수동으로 생성하지 않는 경우가 많지만 다음과 같습니다.
- 사용하다
@Autowired
- 통합 테스트에서 사용되는 클래스에서 사용되는 속성은 직접 사용되는 클래스의 종속성이 크기 때문에 간접적으로 수정하려고 합니다.
그리고 이 해결방법은@SpringBootTest
도움이 될 것 같아요
언급URL : https://stackoverflow.com/questions/23162777/how-do-i-mock-an-autowired-value-field-in-spring-with-mockito
'programing' 카테고리의 다른 글
기능을 통해 자동으로 새 사용자를 생성합니다.WordPress의 php (0) | 2023.03.16 |
---|---|
제품 카테고리에 사용자 정의 필드 추가 (0) | 2023.03.16 |
JsonConvert 사용.Deserialize Object를 사용하여 Json을 C# POCO 클래스로 역직렬화합니다. (0) | 2023.03.16 |
1면 Wordpress의 ID 가져오기 (0) | 2023.03.16 |
JAXB 객체 목록을 JSON으로 커스터마이즈하려면 어떻게 해야 합니까? (0) | 2023.03.16 |