今天我將展示一下我是如何在實際中對dao進行單元測試的
首先我們來確認一下dao需要什么樣的環境,我的dao是用Spring+hibernate來構建的,而對應的數據源是oracle9。所以要進行dao的測試我需要從Spring的連接oracle的context中獲取dao的實例出來,這里我使用的是spring-mock
spring-mock使用比較簡單的,只需要設置spring的配置文件路徑就可以獲得上下文了
這里需要注意的是這個spring上下文是ClassPathApplicationContext,而我們在web環境中經常遇到的是WebApplicationContext

/**?*//**
?*?$Id:$
?*
?*?Copyright?2005?easou,?Inc.?All?Rights?Reserved.
?*/
package?test.spring.common;

import?org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;

import?test.PathConfig;

public?class?BaseSpringTestCase?extends

????????AbstractTransactionalDataSourceSpringContextTests?
{
????

????@Override

????protected?String[]?getConfigLocations()?
{

????????String[]?config?=?PathConfig.springxml;

????????return?config;

????}
????
????

????public?void?testConfig()?
{????????
????????assertNotNull("spring-mock?context?has?bean?init()",this.applicationContext);
????}

}這里testConfig是用來檢查你spring配置的加載是否正確的
下面給出一個DAO的簡單查詢方法

public?List?getHomepageAreasByChannelId(long?channelId)?
{

????????return?this.executeHQL("?from?CsHomepageArea??h?where?h.csChannel.id='"
????????????????+?channelId?+?"'?order?by?h.theOrder");
????}
上面的方法指示根據一個id取列表出來,而我們要測試的目標有(其實也就是我們這個方法要實現的目標):
1、給出正確的id是否能否返回正確的結果
2、返回的結果集能夠根據hibernate配置文件而得到我們期望的結果集(比如說對子集的lazy讀取)
3、返回的結果集是否按照你所期望的排序
4、給出錯誤的id是否在獲取數據時會出錯
根據上面的測試目標我們就很容易的得到下面的測試方法了

public?void?testGetHomepageAreasByChannelId()?
{
????????List?list?=?channelDAO.getHomepageAreasByChannelId(1);
????????assertNotNull("homepage?list?is?not?null",?list);
????????CsHomepageArea?homepage?=?(CsHomepageArea)?list.get(0);
????????assertNotNull("homepage'name?is?not?null",?homepage.getName());
????????assertNotNull("homepage'channel?has?been?lazy",?homepage.getCsChannel()
????????????????.getName());
????????assertNotNull("homepage'column?has?been?lazy",?homepage.getCsColumn()
????????????????.getName());
????????assertNotNull("homepage'subject?has?been?lazy",?homepage
????????????????.getCsSubjects().iterator().next().getName());
????????CsSubject?subject?=?(CsSubject)?homepage.getCsSubjects().iterator()
????????????????.next();
????????assertNotNull("homepage'subject'keyword?has?been?lazy",?subject
????????????????.getCsSubjectKeywords().iterator().next().getName());

????}對于DAO層的查詢方法,我們測試的就是判斷返回的數據是否是我們需要的
下面這個方法是DAO的增改方法,和刪除方法

public?void?saveComment(CsComment?comment)?
{
????????getHibernateTemplate().saveOrUpdate(comment);????????
????}

????public?void?deleteComment(CsComment?comment)?
{????????
????????getHibernateTemplate().delete(comment);????????
????}?
對于這種無返回值得方法我們主要測試的是:
1、對于正確的數據是否能夠正確的存入數據庫或者從數據庫刪除
2、對于錯誤的數據操作能夠有錯誤信息(如主鍵重復)

public?void?testSaveComment()
{
????????CsComment?comment?=?new?CsComment();
????????comment.setCommentDate(new?Date());
????????comment.setContent("comment?test");
????????channelDAO.saveComment(comment);
????????CsComment?dbComment?=(CsComment)channelDAO.getEntity(comment.getId());
????????assertNotNull("comment?has?bean?saved",?dbComment);
????}

????public?void?testDeleteComment()
{
????????CsComment?comment?=?new?CsComment();
????????comment.setId(new?Long(13));
????????channelDAO.delete(comment);
????????CsComment?dbComment?=(CsComment)channelDAO.getEntity(comment.getId());
????????assertNull("comment?has?bean?delete",?dbComment);
????}其實這種save或者delete的方法由于使用時都是基本調用hibernate的方法,所以在我看來測試的意義并不是很大