<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    邊城愚人

    如果我不在邊城,我一定是在前往邊城的路上。

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      31 隨筆 :: 0 文章 :: 96 評論 :: 0 Trackbacks

    ??? ??? 做 java 企業級開發時,我們通常采用三層架構。特別地,如果我們要做的系統的業務邏輯不是很復雜時,我們要處理的不過是 CRUD 操作,這時我們可能將 dao 層與 service 層合并為一層,盡管很多人會這樣做,但我仍傾向于將兩層分開;因為 service dao 不是一一對應的,從復用及邏輯清晰的角度考慮,應該將它們分開。在三層架構下,對于 web 層, service 層, dao 層我們都該怎么測試?這里我將介紹基于 Spring Hibernate DbUnit 的情況下我的測試方法。由于使用了 Spring ,事務管理就不在 dao ,因此要單獨地測試 dao 可能要麻煩一些;另一方面, dao 中的操作大多是簡單的,也不是很值得測試。在使用了 Hibernate Spring 的情況下,我們要測試的除了 HQL ,還有其配置文件,我覺得對數據持久化的測試最好定在 service 上。如果 service 業務邏輯復雜的話,與數據持久化無關的業務邏輯(應該寫在領域對象中)可以單獨測試 ,在保證與數據持久化無關的業務邏輯的正確性下,帶上 dao 操作做集成(單元)測試。

    ??? ??

    在使用 Spring 做測試時,推薦測試類繼承自 Spring AbstractTransactionalDataSourceSpringContextTests ,這也是官方推薦的做法。 AbstractTransactionalDataSourceSpringContextTests 對測試方法提供了事務管理,同時它的依賴注入特性也方便測試類注入被測試類(但我并不認為它的事務管理是很需要的)。承接于上一篇文章中的例子 ,下面給出測試類 AccountServiceTest。


    package ?hibernatesample.service;
    import ?hibernatesample.domain.Account;
    import ?java.io.File;
    import ?java.io.InputStream;
    import ?java.util.List;
    import ?org.dbunit.IDatabaseTester;
    import ?org.dbunit.JdbcDatabaseTester;
    import ?org.dbunit.dataset.IDataSet;
    import ?org.dbunit.dataset.xml.FlatXmlDataSet;
    import ?org.springframework.test.AbstractDependencyInjectionSpringContextTests;
    import ?org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;

    public ? class ?AccountServiceTest? extends ?AbstractTransactionalDataSourceSpringContextTests?{

    ????
    private ?AccountService?accountService;
    ????
    private ?IDatabaseTester?databaseTester;

    ????
    public ?AccountService?getAccountService()?{
    ????????
    return ?accountService;
    ????}
    ????
    ????
    public ?AccountServiceTest() throws ?Exception{
    ????
    ????}

    ????
    public ? void ?setAccountService(AccountService?accountService)?{
    ????????
    this .accountService? = ?accountService;
    ????}

    ????@Override
    ????
    protected ? void ?onSetUp()? throws ?Exception?{
    ????????databaseTester?
    = ? new ?JdbcDatabaseTester( " com.mysql.jdbc.Driver " ,
    ????????????????
    " jdbc:mysql://localhost/HibernateSample " ,? " root " ,? " 0102 " );
    ?????IDataSet?dataSet?
    = ?getDataSet();
    ?????databaseTester.setDataSet(?dataSet?);
    ?????databaseTester.onSetup();
    ????}

    ????@Override
    ????
    protected ? void ?onTearDown()? throws ?Exception?{
    ????????databaseTester.onTearDown();
    ????}

    ????
    protected ?IDataSet?getDataSet()? throws ?Exception?{
    ????????String?path?
    = ? " hibernatesample " + File.separator + " dao " + File.separator + " dataset " + File.separator + " Account.xml " ;
    ????????InputStream?in?
    = ? this .getClass().getClassLoader().getResourceAsStream(path);
    ????????
    return ? new ?FlatXmlDataSet(in);
    ????}
    ????

    ????@Override
    ????
    protected ?String[]?getConfigLocations()?{
    ????????
    ????????
    return ? new ?String[]{ " classpath:service-applicationContext.xml " };
    ????}
    ????
    ????
    public ? void ?testInsert()?{
    ????????Account?a?
    = ? new ?Account();
    ????????a.setName(
    " aa " );
    ????????accountService.insertAccount(a);
    ????????List
    < Account > ?l? = ?accountService.findAllAccount();
    ????????assertEquals(
    3 ,?l.size());
    ????????Account?b?
    = ?l.get( 2 );
    ????????assertEquals(
    " aa " ,?b.getName());
    ????}

    ????
    public ? void ?testFindAll()?{
    ????????List
    < Account > ?l? = ?accountService.findAllAccount();
    ????????assertEquals(
    2 ,?l.size());
    ????????Account?a?
    = ?l.get( 0 );
    ????????assertEquals(
    new ?Long( 1 ),?a.getId());
    ????????assertEquals(
    " kafka " ,?a.getName());
    ????????Account?b?
    = ?l.get( 1 );
    ????????assertEquals(
    new ?Long( 2 ),?b.getId());
    ????????assertEquals(
    " 0102 " ,?b.getName());
    ????}
    }

    ??? ??? 由于 AccountServiceTest 繼承了 AbstractTransactionalDataSourceSpringContextTests ,因此使用 D b Unit 時就不能繼承 DBTestCase ,這里采用的方法就是在 onSetUp() 中實現數據集的裝入。由于 AbstractTransactionalDataSourceSpringContextTests 最第 N 個頂層的父類繼承于 Junit ,所以 onSetUp() 將在 SetUp() 中被調用,默認的 onSetUp() 實現為空; onTearDown() 的原理和 onSetUp() 相似。由于 AbstractTransactionalDataSourceSpringContextTests 具有依賴注入的特性,所以被測試對象 accountService 可以通過 setter 方法獲得;當然,我們也可以在構造函數中通過 Bean 工廠獲得 accountService protected String[] getConfigLocations() 返回的數組為 Spring Beans 配置文件的位置。

    ??? ??? 對于與測試相關的其他類,這里就不給出了。通過使用 DbUnit ,我覺得測試持久化操作時方便了許多。不爽的地方在于,在使用了 Spring Hibernate 的情況下,測試一個方法有些耗時,這自然不單單是 DbUnit 的問題。但如果我將 dao service 的測試放在一起來做,這種耗時也只能忍著。再說一下 web 層的測試,我當前使用的 web 框架是 Webwork ,在測試 Action 的時候,對于 Web 請求之類使用 Mock ,對于 Service 的調用有時 Mock 有時真實調用。 Mock 的好處是耗時能少一些,但寫 Mock 代碼也很繁瑣,而對 service Mock 有時本身就失掉了測試的意義。

    posted on 2007-06-14 09:18 kafka0102 閱讀(1475) 評論(0)  編輯  收藏 所屬分類: TDD

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 久久丫精品国产亚洲av不卡| 久久激情亚洲精品无码?V| 久久亚洲私人国产精品vA| 中文在线观看免费网站| 中文字幕精品无码亚洲字| 国产黄片不卡免费| 久久精品国产亚洲沈樵| APP在线免费观看视频| 亚洲AV无码成人网站久久精品大| 中国精品一级毛片免费播放| 夜夜春亚洲嫩草影院| 永久免费不卡在线观看黄网站| 亚洲AV无码不卡在线播放| 18级成人毛片免费观看| 2020天堂在线亚洲精品专区| 国内自产少妇自拍区免费| 风间由美在线亚洲一区| 亚洲精品人成无码中文毛片 | 美女被免费视频网站| 亚洲成人高清在线| 成人无码视频97免费| 91精品国产亚洲爽啪在线观看| 1000部拍拍拍18勿入免费凤凰福利| 99久久婷婷国产综合亚洲| 亚洲AV日韩精品一区二区三区| 777亚洲精品乱码久久久久久 | 日本特黄特色aa大片免费| 日韩精品无码免费视频| 国产精品亚洲成在人线| 在线观看www日本免费网站| 亚洲码欧美码一区二区三区| 亚洲精品动漫人成3d在线| 午夜精品免费在线观看| 亚洲国产精品无码久久九九大片| 亚洲精品老司机在线观看| 污污网站免费观看| 精品亚洲视频在线| 无码久久精品国产亚洲Av影片 | 无人视频免费观看免费视频| 亚洲精品无码av人在线观看| 国产无人区码卡二卡三卡免费|