<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

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


    網站導航:
     
    主站蜘蛛池模板: 免费黄网站在线看| 国产99精品一区二区三区免费| 亚洲性无码AV中文字幕| 在线观看亚洲免费视频| 中国一级全黄的免费观看| 18pao国产成视频永久免费| 免费高清小黄站在线观看| 亚洲无线码在线一区观看| 亚洲精品视频观看| 日韩欧美亚洲国产精品字幕久久久 | 亚洲第一AAAAA片| 亚洲午夜国产精品无卡| 亚洲AV无码XXX麻豆艾秋| 成人妇女免费播放久久久| 亚欧免费视频一区二区三区| 国产青草视频在线观看免费影院| 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲精品国产成人| 美女羞羞免费视频网站| 久久久久成人精品免费播放动漫| 午夜性色一区二区三区免费不卡视频 | 亚洲av无码专区国产乱码在线观看| 亚洲另类春色校园小说| 黄色免费在线网址| 91在线老王精品免费播放| 国产免费观看青青草原网站| 亚洲av午夜福利精品一区| 亚洲国产精品ⅴa在线观看| 成人久久免费网站| 免费无码成人AV片在线在线播放| 国产亚洲美女精品久久久久狼| 亚洲精品第一国产综合野| 在线观看免费视频一区| 成年男女男精品免费视频网站| 亚洲日韩在线中文字幕第一页| 亚洲国产中文在线视频| fc2成年免费共享视频网站| 三年片在线观看免费观看高清电影 | 亚洲AV无码国产精品永久一区| 久久精品国产大片免费观看| 国产zzjjzzjj视频全免费|