Spring 3.1.4.RELEASE 및 Mockito 1.9.5를 사용하고 있습니다. 내 Spring 수업에는 다음이 있습니다.
@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”필드 만 그대로 유지하고 싶습니다. 또한 setDefaultUrl
클래스에 명시적인 “setter”메소드 (예 :)가 없으며 테스트 목적으로 만 생성하고 싶지 않습니다.
이를 감안할 때 해당 필드의 값을 어떻게 모의 할 수 있습니까?
답변
ReflectionTestUtils.setField
코드를 수정하는 것을 피하기 위해 Spring의 마법을 사용할 수 있습니다 .
이 방법은 사용하기 매우 쉽기 때문에 필요하지 않을 수 있지만 더 자세한 정보는 이 튜토리얼을 확인하십시오.
최신 정보
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")
답변
속성 구성을 테스트 클래스로 모의 할 수도 있습니다.
@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);
}
}
답변
클래스 @Value
를 사용하는 대신 -annotated 필드를 생성자에 매개 변수로 전달하는 관련 솔루션을 제안하고 싶습니다 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) 테스트를 구현 세부 사항에 연결하지 않습니다 (반영은 문자열을 사용하여 필드 이름에 연결하고 필드 이름을 변경하면 문제가 발생할 수 있습니다.)
답변
이 마법의 Spring Test 주석을 사용할 수 있습니다.
@TestPropertySource(properties = { "my.spring.property=20" })
org.springframework.test.context.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;
...
답변
나는 아래 코드를 사용했고 그것은 나를 위해 일했습니다.
@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)가 없으며 테스트 목적으로 만 생성하고 싶지 않습니다.
이를 해결하는 한 가지 방법은 생성자 주입 을 사용하도록 클래스를 변경하는 것입니다. 은 테스트 및 Spring 주입에 사용되는 입니다. 더 이상 반사하지 마세요 🙂
따라서 생성자를 사용하여 모든 문자열을 전달할 수 있습니다.
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");