2012-05-03 86 views
0

我最近碰到一個類凸輪這樣的:春季註釋 - 好還是壞?

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字符串測試這個類。據我所看到的,有兩種可選方式:

  1. 最多可以裝入,這將是緩慢的,最有可能加載了一大堆的東西,我不需要爲測試
  2. 應用上下文使用反射Spring註解之前設置的專用屬性和調用私有postConstruct()方法

在未來的日子,類會被寫成這樣:

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應用上下文來使用它們和時間?

謝謝, 蘭斯。

回答

4

爲什麼不用mock的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; 
    } 

} 

因此,而不是在自動裝配放棄,你實際上可以利用它。此外,您還可以將加載的上下文限制爲受測試的類所需的內容。

+0

這絕對是真棒,是我想要的東西。感謝soulcheck。 –

0

您仍然可以在setter和構造函數上使用註釋,這是我個人比較喜歡的,因爲它使得依賴關係更加明顯。這50個參數構造函數真的很突出。

2

我認爲即使對於所需的依賴關係,傾向於使用setter注入(甚至注入到private字段中)的構造函數注入也是不健康的傾向。

注意,由於在這個例子中都dependncies都需要它可以被重寫如下:

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註釋的問題,這是不正確的使用他們的問題。

+0

你能否提供一些推理說明爲什麼你發現二傳手/田地注射是「不健康的」?在我看來,當你有像Mockito這樣簡單的替代方案或者發佈的解決方案soulcheck時,爲你已經列出的元素添加一個構造函數實質上是代碼重複,因此簡單地是混亂。我很難考慮一個*單一的*好的理由*而不是*使用現場注入。它的製作速度一樣快,寫得更快,雜亂無章,更清晰......那麼爲什麼你不喜歡它呢? –

0

儘管我同意axtavt的回答,但一個快速的解決方法是使用spring-test工件中的ReflectionTestUtils類。它提供了很好的單行這樣的場景:

ReflectionTestUtils.setField(dao, "dataSource", mydataSource); 

單元測試,這是因爲它得到一樣簡單。

ReflectionTestUtils

+0

我真的不喜歡這種方法,我覺得它很黑。我也需要反思地調用postConstruct()方法。再次,哈克。 –

+0

我知道,因爲這個原因我不喜歡私人註釋字段。但這是解決這個問題最簡單的方法。 –

+0

我不同意,soulcheck提供了一種使用@Configuration注入依賴關係的好方法。它比手動反射要乾淨得多。 –