用Unitils測試BaseDao遇到的問題總結

mingziday發表於2015-07-16

《Spring 3.0就這麼簡單》.(陳雄華,林開雄)第8章,對如何用Unitils進行測試簡單介紹,下面是我用Unitils進行單元測試過程中遇到的問題的總結。

1、設定好pom.xml依賴後,pom檔案報錯:Missing artifact javax.transaction:jta:jar:1.0.1B

原因是本地maven庫中缺少jta-1_0_1B-classes這個jar,需要把這個jar安裝到本地庫中去。
下載包含此jar的zip包,地址:http://download.csdn.net/detail/spring123tt/6847843
cmd到zip包的目錄,執行下面的字串
mvn install:install-file -Dfile=./jta-1_0_1B-classes.zip -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dpackaging=jar

2、用Excel檔案作為驗證資料的輸入源,執行TestNG的時候報錯:
java.lang.NoClassDefFoundError: org/apache/poi/hssf/usermodel/HSSFWorkbook
Caused by: java.lang.ClassNotFoundException: org.apache.poi.hssf.usermodel.HSSFWorkbook

原因:java在操作Excel等Office檔案時,需要引入poi支援,所以需要在pom.xml中加入包依賴
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>

3、執行TestNG報錯:
java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFDateUtil.isCellDateFormatted(Lorg/apache/poi/hssf/usermodel/HSSFCell;)

原因:dbunit對poi支援不夠好,詳見http://stamen.iteye.com/blog/1478022

更新dbunit版本到最新的2.5.1解決

4、執行TestNG報錯:
org.apache.commons.beanutils.ConversionException: No value specified for 'Date'

原因:beanutils用到了時間等非內建物件時,如果物件為NULL則,會出現此異常

我的這個測試用例的目的是將Excel中的多行資料插入到資料庫裡面去,很顯然,要插入的資料裡面Date型別出現了null值。

先在XlsDataSetBeanFactory.createbeans方法中把讀取到的資料逐行列印出來,看看到底哪些資料在搗鬼。我的Excel資料是這樣的:

而實際列印的資料卻出現了:

stu_netname:null
stu_password:null
stu_realname:null
stu_registdate:null

雖然Excel檔案中有幾行用看上去都是空白,但是實際上很可能是新增了空格在裡面,從而引起類似的錯誤,解決方法就是把Excel檔案中真實資料下面的幾行刪掉。

另外,通過google搜尋到了另外的解決方法,思路是遇到Null值得時候進行規避而不是報錯:http://www.blogjava.net/javagrass/archive/2011/10/10/352856.html

5、執行TestNG報錯:
org.dbunit.DatabaseUnitRuntimeException: At least one column is required to build a valid select statement

起因是新版本的dbunit細化了各種資料庫的MetadataHandler的處理,為每一種資料庫提供了一個MetadataHandler,如MySqlMetadataHandler,Db2MetadataHandler等。而unitils並沒有升級,仍然使用dbunit提供的DefaultMetadataHandler。這個DefaultMetadataHandler並不能很好的處理各個資料庫之間的不同,所以會導致相容問題。

解決方案:寫一個擴充類MySqlDbUnitModule繼承 DbUnitModule,

public final class MySqlDbUnitModule extends DbUnitModule {
 
    @Override
    public DbUnitDatabaseConnection getDbUnitDatabaseConnection(final String schemaName) {
        DbUnitDatabaseConnection result = dbUnitDatabaseConnections.get(schemaName);
        if (null != result) {
            return result;
        }
        result = super.getDbUnitDatabaseConnection(schemaName);
        result.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());
        result.getConfig().setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler());
        return result;
    }
}

使用新建的MySqlDbUnitModule替換預設的DbUnitModule。這個就比較簡單了,在unitils.properties中加入:
unitils.module.dbunit.className=com.miraclesea.test.database.module.MySqlDbUnitModule

該問題參考:http://my.oschina.net/u/719192/blog/173644

6、我的bean宣告採用,註解+自動掃描的方式:

<context:component-scan base-package="com.huawei.happycar.dao.impl,com.huawei.happycar.service.impl" />

我的業務裡面定義為:

@Service("studentServiceBean")
public class StudentServiceImpl implements StudentService {}

對studentServieBean,TestNG執行的時候就會報錯(意思是找不到這個bean):
Unable to assign the Spring bean value to field annotated with @SpringBean 
Unable to assign the value to field: studentServiceImpl. Ensure that this field is of the correct type. Value: com.huawei.happycar.service.impl.StudentServiceImp

如果我定義為:

@Service("studentServiceBean")
public class StudentServiceImpl  {}

對studentServieBean,TestNG執行的時候沒有一點問題。

另外,如果我用Junit的方法測試,兩種方法都沒有問題,該問題我還沒有解決,懷疑是Unitils的bug


使用Excel作為資料來源進行Unitils測試時,要注意的問題

1、unitils配置檔案的設定中如下兩項要按照實際的路徑進行修改

DbUnitModule.DataSet.factory.default=com.huawei.happycartest.dataset.excel.MultiSchemaXlsDataSetFactory
DbUnitModule.ExpectedDataSet.factory.default=com.huawei.happycartest.dataset.excel.MultiSchemaXlsDataSetFactory

2、測試方法

public class StudentDaoTest extends BaseDaoTest {
    @SpringBean("StudentDaoImpl")
    private StudentDaoImpl StudentDaoImpl;
    @Test
    @ExpectedDataSet("StudentDao.SaveStudents.xls")
    public void saveUsers()throws Exception  {
        List<Student> users  = XlsDataSetBeanFactory.createBeans(StudentDaoTest.class,"StudentDao.SaveStudents.xls", "t_student", Student.class);
        for(Student u:users){
            StudentDaoImpl.save(u);
        }
    }
}

上面的寫法中StdentDao.SaveStudents.xml一定要和StudentDaoTest.class在一個目錄下。


使用Junit方法的測試

    @Test
    public void test() {
        ApplicationContext ac = new ClassPathXmlApplicationContext(
                new String[] { "applicationContext.xml", "spring-hibernate.xml" });
        // 從Spring的IOC容器中獲取bean物件
        StudentService userService = (StudentService) ac.getBean("studentServiceBean");
        // 執行測試方法
        List<Student> list = userService.listAllStudent();
        for(Student stu : list)
        {
            System.out.println(stu.getStuNetname());
        }
    }

這個Unitils測試框架官網上維護更新非常慢,Unitils的官方最新版本是3.3,對應的釋出時間是2011年12月22號。
所以顯然它不能支援Hibernate4了,另外就是Spring4估計也不是完美。
支援決定放棄使用這個測試框架,學習一下spring test。

相關文章