我最近喜欢这样的课程:
public class SomeDao {
@Inject
private DataSource dataSource;
@Value("#{someMap['someDao.sql']}")
private String sql;
private JdbcTemplate jdbcTemplate;
@PostConstruct
private void postConstruct() {
jdbcTemplate = new JdbcTemplate(dataSource);
}
...
}
现在我想通过注入DataSource和SQL字符串对这个类进行单元测试。据我所知,有两种选择:
在春季注释之前的几天,这个课程就像这样写了:
public class SomeDao {
private String sql;
private JdbcTemplate jdbcTemplate;
public SomeDao(DataSource dataSource, String sql) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.sql = sql;
}
...
}
我可以很容易地测试这个课程而不需要反射或弹簧。我的班级是一个纯粹的pojo,没有春天的依赖。
那么,春季注释是好事还是倒退了?是否有时候我应该使用它们以及何时应该使用旧的XML应用程序上下文?
谢谢, 喷枪。
答案 0 :(得分:4)
为什么不用模拟bean声明测试上下文并从中注入类所需的那些?这就是人们通常做的事情,而且很简单。
最轻量级的方法是在测试类中提供一个内部类,使用@Configuration
注释,该类具有提供模拟的方法:
@Configuration
public class DataAccessConfiguration {
@Bean
public DataSource dataSource() {
DataSource dataSource = mock(Datasource.class);
return dataSource;
}
@Bean
public Map<String,String> someMap() {
Map<String, String> map = new HashMap<>();
map.put("someDao.sql", "somevalue");
return map;
}
}
因此,您可以实际利用它,而不是放弃自动装配。您还可以将加载的上下文限制为被测试类所需的内容。
答案 1 :(得分:2)
我认为有一种不健康的倾向,即使对于所需的依赖项,也更倾向于使用setter注入(甚至注入private
字段)而不是构造函数注入。
请注意,由于此示例中的两个依赖项都是必需的,因此可以按如下方式重写:
public class SomeDao {
private String sql;
private JdbcTemplate jdbcTemplate;
@Inject
public SomeDao(
DataSource dataSource,
@Value("#{someMap['someDao.sql']}") String sql) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.sql = sql;
}
...
}
所以,这不是Spring注释的问题,不正确使用它们是一个问题。
答案 2 :(得分:0)
您仍然可以在setter和构造函数上使用注释,我个人更喜欢这样,因为它使依赖更加明显。这50个参数构造函数确实很突出。
答案 3 :(得分:0)
虽然我同意axtavt的回答,但一个快速的解决方法是使用spring-test工件中的ReflectionTestUtils
类。它为这种情况提供了很好的单行:
ReflectionTestUtils.setField(dao, "dataSource", mydataSource);
对于单元测试,这很简单。