Как я могу издеваться над полем autowired @Value весной с помощью Mockito?
Я использую Spring 3.1.4.Релиз и Mockito 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". Также обратите внимание, что у меня нет явных методов "сеттера" (например,setDefaultUrl
) в моем классе, и я не хочу создавать каких-либо просто для проверки.
учитывая это, как я могу издеваться над значением для этого одного поля?
5 ответов
вы можете использовать магию весны ReflectionTestUtils.setField
во избежание внесения каких-либо изменений в ваш код.
проверить этой учебник для получения дополнительной информации, хотя вам, вероятно, не понадобится, так как метод очень прост в использовании
обновление
С момента введения весной 4.2.RC1 теперь можно установить статическое поле без необходимости предоставления экземпляра класса. См.этой часть документации и этой commit.
это был третий раз, когда я гуглил себя до этого, так как я всегда забываю, как издеваться над полем @Value. Хотя принятый ответ верен, мне всегда нужно некоторое время, чтобы получить правильный вызов "setField", поэтому, по крайней мере, для себя я вставляю фрагмент примера здесь:
категории:
@Value("#{myProps[‘some.default.url']}")
private String defaultUrl;
тест класс:
import org.springframework.test.util.ReflectionTestUtils;
ReflectionTestUtils.setField(myClassUnderTest, "defaultUrl", "http://foo");
// Note: Don't use MyClassUnderTest.CLASS, use the class 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
-аннотированные поля в качестве параметров конструктора вместо использования 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) мы не связываем наш тест с нашим детали реализации (отражение связывает нас с именем поля с помощью строки, Что может вызвать проблему, если мы изменим имя поля).
вы можете использовать эту магическую весеннюю тестовую аннотацию:
@TestPropertySource(properties = { "my.spring.property=20" })
посмотреть org.springframework.тест.контекст.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;
...