Как я могу издеваться над полем 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;
   ...