Java Spring注释-好还是坏?
我最近遇到过这样一个班:Java Spring注释-好还是坏?,java,spring,unit-testing,spring-annotations,Java,Spring,Unit Testing,Spring Annotations,我最近遇到过这样一个班: public class SomeDao { @Inject private DataSource dataSource; @Value("#{someMap['someDao.sql']}") private String sql; private JdbcTemplate jdbcTemplate; @PostConstruct private void postConstruct() { jdbcTemp
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);
}
...
}
public class SomeDao {
private String sql;
private JdbcTemplate jdbcTemplate;
public SomeDao(DataSource dataSource, String sql) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.sql = sql;
}
...
}
现在,我想通过注入数据源和SQL字符串来对这个类进行单元测试。据我所知,有两种选择:
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);
}
...
}
public class SomeDao {
private String sql;
private JdbcTemplate jdbcTemplate;
public SomeDao(DataSource dataSource, String sql) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.sql = sql;
}
...
}
我可以很容易地测试这个类,而不需要反射或spring。我的类是纯pojo,没有spring依赖项
那么,spring注释是一件好事还是一种倒退?是否有应该使用它们的时候,以及应该使用旧的XML应用程序上下文的时候
谢谢,
Lance.您仍然可以在setter和constructor上使用注释,我个人更喜欢这种注释,因为它使依赖关系更加明显。这50个参数构造函数真的很突出。为什么不用模拟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;
}
}
@配置
公共类DataAccessConfiguration{
@豆子
公共数据源数据源(){
DataSource DataSource=mock(DataSource.class);
返回数据源;
}
@豆子
公共地图someMap(){
Map Map=newhashmap();
map.put(“someDao.sql”、“somevalue”);
返回图;
}
}
因此,与其放弃自动布线,您实际上可以利用它。此外,您还将加载的上下文限制为被测试类所需的内容。我想说的是,与构造函数注入相比,存在一种不健康的倾向,即即使对于所需的依赖项,也更喜欢setter注入(甚至是注入到
私有
字段中)
注意,由于本例中的两个依赖项都是必需的,因此可以按如下方式重写:
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注释的问题,而是错误使用它们的问题。虽然我同意axtavt的答案,但一个快速解决方法是使用Spring测试工件中的
ReflectionTestUtils
类。它为这样的场景提供了很好的一行程序:
ReflectionTestUtils.setField(dao, "dataSource", mydataSource);
对于单元测试,这是最简单的
看这绝对是太棒了,正是我想要的。谢谢soulcheck。我真的不喜欢这种方法,而且我觉得它很粗糙。我还需要反射地调用postConstruct()方法。再一次,哈奇。我知道,出于这个原因,我根本不喜欢私人注释字段。但这是解决这个问题的最简单方法。我不同意,soulcheck提供了一种使用@Configuration注入依赖项的极好方法。它比手动反射干净得多。@uklance它很好,当然也更干净,但我还是要说我的方法更简单。重构代码时反射不会重构。ReflectionTestUtils也不允许我调用私有方法。您能提供一些理由说明为什么您发现setter/field-inject“不健康”吗?在我看来,当你有一些简单的选择,比如Mockito或者soulcheck发布的解决方案时,为你已经列出的元素添加一个构造函数本质上是代码重复,因此,就是混乱。我很难想出一个不使用现场注射的好理由。它的生产速度一样快,书写速度更快,杂乱程度更低,更清晰。。。那么你为什么不喜欢它呢?@TimPote:我可以想出几个反对场注入的理由:没有反射或spring之类的框架就无法进行测试;不会使依赖关系显式化;创建上帝类太容易了;你很容易错过“太多依赖”的味道;字段不能是
final
,即使它们应该是不可变的…