在unit testing期间填充Spring @Value
我正在为我的程序中使用的一个简单的bean编写unit testing来validation表单。 该bean用@Component
注解,并有一个类variables,它是使用@Value("${this.property.value}") private String thisProperty;
初始化@Value("${this.property.value}") private String thisProperty;
我想为这个类中的validation方法编写unit testing,但是,如果可能的话,我想这样做,而不使用属性文件。 我背后的推理是,如果我从属性文件拉的值发生变化,我希望不会影响我的testing用例。 我的testing用例正在testingvalidation值的代码,而不是值本身。
有没有一种方法可以在我的testing类中使用Java代码来初始化Java类,然后在该类中填充Spring @Value属性,然后使用它来testing?
我没有find这个如何似乎是接近,但仍然使用属性文件。 我宁愿这一切都是Java代码。
谢谢
如果可能的话,我会尝试写没有Spring上下文的testing。 如果你在没有弹簧的情况下在你的testing中创build这个类,那么你可以完全控制它的字段。
要设置@value
字段,您可以使用Springs ReflectionTestUtils
– 它有一个方法setField
来设置专用字段。
@see JavaDoc:ReflectionTestUtils.setField(java.lang.Object,java.lang.String,java.lang.Object)
如果你愿意,你仍然可以在Spring Context中运行你的testing,并在Springconfiguration类中设置所需的属性。 如果您使用JUnit,请使用SpringJUnit4ClassRunner并为您的testing定义专门的configuration类,如下所示:
被测class:
@Component public SomeClass { @Autowired private SomeDependency someDependency; @Value("${someProperty}") private String someProperty; }
testing类:
@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() { ... } }
和这个testing的configuration类:
@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); } }
说了这么多,我不会推荐这种方法,我只是在这里添加它供参考。 在我看来,更好的方法是使用Mockito亚军。 在这种情况下,你根本不需要在Spring里面运行testing,这更简单明了。
自Spring 4.1以来,您可以在unit testing级别上使用org.springframework.test.context.TestPropertySource
注释来设置属性值。 甚至可以使用这种方法将属性注入到依赖bean实例中
例如
@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(); } } }
注意:在Spring上下文中必须有org.springframework.context.support.PropertySourcesPlaceholderConfigurer
实例
编辑24-08-2017:如果您使用SpringBoot 1.4.0及更高版本,则可以使用@SpringBootTest
和@SpringBootConfiguration
注释初始化testing。 更多信息在这里
在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); } }
这似乎工作,虽然仍然有点冗长(我想更短的东西仍然):
@BeforeClass public static void beforeClass() { System.setProperty("some.property", "<value>"); } // Optionally: @AfterClass public static void afterClass() { System.clearProperty("some.property"); }
在configuration中添加PropertyPlaceholderConfigurer正在为我工作。
@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; }
}
并在testingclass
@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()); }
}