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

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

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

    qileilove

    blog已經轉移至github,大家請訪問 http://qaseven.github.io/

    DAO test

    至此,一個基于MVC的基本Android應用程序已經初步形成了。
      下面我們來實現一個具有TabHost的布局的典型Android應用,由于我們基本上可以不考慮Android 4.x以前的版本,因此我對TabHost布局的實現將采用Fragment來實現,而不是采用舊的ActivityGroup來實現。
      同時,我們希望我們的應用程序可以適用于不同的項目,因此需要TabHost上的圖片及文字可以非常方便的進行更換。我們采用下部有5個選項的布局,其中中間的選項可以突出顯示,選中某個選項,目前僅顯示對應Fragmentation的名字。
      好了,需求基本說清楚了,下面我們就開始一步步實現吧。
      首先是基于Fragment的TabHost布局實現,原理很簡單,在MainActivity的布局文件里添加如下代碼即可:
    <?xml version="1.0" encoding="utf-8"?>
    <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <!-- 實現Tab標簽的居底主要是通過設置屬性 android:layout_weight="1" -->
    <!-- 還要注意FrameLayout標簽的位置,要寫在TabWidget標簽的前面 -->
    <FrameLayout
    android:id="@android:id/tabcontent"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_gravity="center_horizontal"
    android:layout_weight="1">
    <fragment
    android:id="@+id/j_dynamicFragment"
    android:name="com.bjcic.wkj.gui.DynamicFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    <fragment
    android:id="@+id/j_findFragment"
    android:name="com.bjcic.wkj.gui.FindFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    <fragment
    android:id="@+id/j_shareFragment"
    android:name="com.bjcic.wkj.gui.ShareFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    <fragment
    android:id="@+id/j_snsFragment"
    android:name="com.bjcic.wkj.gui.SnsFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    <fragment
    android:id="@+id/j_moreFragment"
    android:name="com.bjcic.wkj.gui.MoreFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
    </FrameLayout>
    <TabWidget
    android:id="@android:id/tabs"
    android:layout_width="fill_parent"
    android:layout_height="60dip"
    android:layout_gravity="center_horizontal"
    android:layout_marginLeft="-2dp"
    android:layout_marginRight="-2dp"
    android:background="@null" />
    </LinearLayout>
    </TabHost>
    好的單元測試應該是原子性的,獨立的,不應依賴其他測試和上下文,但是要測試數據讀寫是否正確,就必須涉及初始數據的加載,數據修改的還原等操作。對于初始數據的加載,手動輸入很麻煩,一個解決方案就是使用Dbunit,從Xml文件甚至Excel中加載初始數據到數據庫,是數據庫的值達到一個已知狀態。同時還可以使用Dbunit,對數據庫的結果狀態進行判斷,保證和期望的一致。數據修改的還原,可以依賴Spring TransactionalTests,在測試完成后回滾數據庫。
      Dbunit還可以對數據的現有數據進行備份,還原,清空現有數據,一個好的測試實踐是每一個開發人員一個測試數據庫,進而對數據庫的數據狀態有更好的控制,但現實可能會是共享同一個測試庫,所以這種情況下,測試的編寫必須多做一些考慮。
      待測試的類:
    package com.test.dbunit.dao.impl;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import org.springframework.jdbc.core.RowMapper;
    import com.test.dbunit.dao.UserDao;
    import com.test.dbunit.entity.User;
    public class DefaultUserDao extends BaseDao implements UserDao {
    private static String QUERY_BY_NICK = "select * from user where user.nick = ?";
    private static String REMOVE_USER = "delete from user where user.nick = ?";
    private static String INSERT_USER = "insert into user(nick,password) values(?, ?)";
    private static String UPDATE_USER = "update user set user.password = ? where user.nick = ?";
    @Override
    public User getUserByNick(String nick) {
    return (User) getJdbcTemplate().queryForObject(QUERY_BY_NICK,new Object[]{nick}, new RowMapper(){
    @Override
    public Object mapRow(ResultSet rs, int index) throws SQLException {
    User user = new User();
    user.setNick(rs.getString("nick"));
    user.setPassword(rs.getString("password"));
    return user;
    }
    });
    }
    @Override
    public void remove(String nick) {
    getJdbcTemplate().update(REMOVE_USER, new Object[]{nick});
    }
    @Override
    public void save(User user) {
    getJdbcTemplate().update(INSERT_USER, new Object[]{user.getNick(), user.getPassword()});
    }
    @Override
    public void update(User user) {
    getJdbcTemplate().update(UPDATE_USER, new Object[]{user.getPassword(), user.getNick()});
    }
    }
      單元測試:
      需要注意的地方就是,DataSourceUtils.getConnection(datasource) , 通過這種方式獲得數據庫連接初始化Dbunit,能夠保證Dbunit使用的數據連接和當前事務的數據庫連接相同,保證能夠在參與到事務中。Spring的TransactionManager會在開始事務時把當前連接保存到ThreadLocal中,DataSourceUtils.getConnection方法,首先從ThreadLocal中獲取連接。
      user001.xml
      Xml代碼
    <?xml version="1.0" encoding="UTF-8"?>
    <dataset>
    <user nick="user001" password="password001" />
    </dataset>
      使用dbunit,可以通過xml文件定義數據集,也可以使用其他方式定義,比如Excel,編程方式。
      Dbunit的主要構件
      IDatabaseConnection
      數據庫鏈接。實現類有DatabaseConnection 和DatabaseDataSourceConnection ,執行數據庫操作時需要一個連接。
      IDataSet
      數據集,數據集可以從Xml文件Excel等外部文件獲取,也可以從數據庫查詢,或者編程方式構件,數據集可以作為初始數據插入到數據庫,也可以作為斷言的依據。另外還有IDatatable等輔助類。
      比如在updateUser測試中,使用了QueryDataSet,從數據庫中構建一個Dataset,再通過FlatXmlDataSet從Xml文件中構建一個Dataset,斷言這兩個Dataset相同。
    QueryDataSet actual = new QueryDataSet(conn);
    actual.addTable("user", "select * from user where user.nick = 'user001'");
    IDataSet expected = new FlatXmlDataSet(new ClassPathResource(
    "com/taobao/dbunit/dao/user001_updated.xml").getFile());
    Assertion.assertEquals(expected, actual);
    DatabaseOperation


      通過定義的靜態字段可以獲取一組代表一個數據操作的子類對象,比如DatabaseOperation .INSERT,返回 InsertOperation,通過執行execute方法把數據集插入到數據庫。例如:
      IDataSet origen = new FlatXmlDataSet(new ClassPathResource(
      "com/taobao/dbunit/dao/user001.xml").getFile());
      DatabaseOperation.INSERT.execute(conn, origen);
      從Xml文件中構建DataSet,使用Insert插入到數據庫,初始化測試數據。
      Assertion
      唯一的方法,assertEqual,斷言兩個數據集或數據表相同。
      更多關于Dbunit的組件的介紹:http://www.dbunit.org/components.html
      PS:使用Oracle的時候,初始化DatabaseConnection需要傳入scheme。new DatabaseConnection(conn,SCHEMA_NAME ) ,SCHMEA_NAME需要大寫。
      附件提供所有代碼下載
    package com.taobao.dbunit.dao;
    import java.sql.SQLException;
    import javax.sql.DataSource;
    import org.dbunit.Assertion;
    import org.dbunit.database.DatabaseConnection;
    import org.dbunit.database.IDatabaseConnection;
    import org.dbunit.dataset.DataSetException;
    import org.dbunit.dataset.DefaultDataSet;
    import org.dbunit.dataset.DefaultTable;
    import org.dbunit.dataset.IDataSet;
    import org.dbunit.dataset.xml.FlatXmlDataSet;
    import org.dbunit.operation.DatabaseOperation;
    import org.junit.Assert;
    import org.junit.Before;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.jdbc.datasource.DataSourceUtils;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
    import org.springframework.test.context.transaction.TransactionConfiguration;
    @ContextConfiguration(locations = { "classpath:testApplicationContext.xml" })
    @TransactionConfiguration(defaultRollback = true)
    public class BaseDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
    @Autowired
    private DataSource dataSource;
    private IDatabaseConnection conn;
    @Before
    public void initDbunit() throws Exception {
    conn = new DatabaseConnection(DataSourceUtils.getConnection(dataSource));
    }
    /**
    * 清空file中包含的表中的數據,并插入file中指定的數據
    *
    * @param file
    * @throws Exception
    */
    protected void setUpDataSet(String file) throws Exception {
    IDataSet dataset = new FlatXmlDataSet(new ClassPathResource(file)
    .getFile());
    DatabaseOperation.CLEAN_INSERT.execute(conn, dataset);
    }
    /**
    * 驗證file中包含的表中的數據和數據庫中的相應表的數據是否一致
    *
    * @param file
    * @throws Exception
    */
    protected void verifyDataSet(String file) throws Exception {
    IDataSet expected = new FlatXmlDataSet(new ClassPathResource(file)
    .getFile());
    IDataSet dataset = conn.createDataSet();
    for (String tableName : expected.getTableNames()) {
    Assertion.assertEquals(expected.getTable(tableName), dataset
    .getTable(tableName));
    }
    }
    /**
    * 清空指定的表中的數據
    *
    * @param tableName
    * @throws Exception
    */
    protected void clearTable(String tableName) throws Exception {
    DefaultDataSet dataset = new DefaultDataSet();
    dataset.addTable(new DefaultTable(tableName));
    DatabaseOperation.DELETE_ALL.execute(conn, dataset);
    }
    /**
    * 驗證指定的表為空
    *
    * @param tableName
    * @throws DataSetException
    * @throws SQLException
    */
    protected void verifyEmpty(String tableName) throws DataSetException,
    SQLException {
    Assert.assertEquals(0, conn.createDataSet().getTable(tableName)
    .getRowCount());
    }
    }
      使用:
    @Test
    public void updateUser() throws Exception {
    setUpDataSet("com/taobao/dbunit/dao/user001.xml");
    User user = new User();
    user.setNick("user001");
    user.setPassword("password002");
    userDao.update(user);
    verifyDataSet("com/taobao/dbunit/dao/user001_updated.xml");
    }

    posted on 2013-12-23 10:13 順其自然EVO 閱讀(227) 評論(0)  編輯  收藏 所屬分類: 數據庫

    <2013年12月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 日木av无码专区亚洲av毛片| 亚洲AV无码成H人在线观看| 亚洲精品乱码久久久久66| 日韩在线一区二区三区免费视频| 成人女人A级毛片免费软件| 亚洲一卡2卡4卡5卡6卡残暴在线| 成人免费视频网站www| 亚洲三级在线播放| 免费人成在线视频| 麻豆亚洲AV成人无码久久精品 | 久久久影院亚洲精品| 免费观看在线禁片| 亚洲一卡2卡三卡4卡有限公司| 免费污视频在线观看| 久久亚洲国产精品成人AV秋霞| 日本h在线精品免费观看| 亚洲依依成人精品| 岛国大片免费在线观看| 国产精品亚洲综合一区在线观看| 亚洲AⅤ优女AV综合久久久| 国内精品99亚洲免费高清| 4444亚洲国产成人精品| 好吊妞788免费视频播放| 黄色三级三级三级免费看| 国产亚洲精品美女久久久| 免费看又黄又无码的网站| 亚洲国产视频久久| 亚洲一级黄色视频| 中文字幕视频免费| 亚洲AV色无码乱码在线观看| 在线播放亚洲第一字幕| 国产精品爱啪在线线免费观看| 亚洲AV无码国产精品永久一区| 久久久久亚洲AV成人网人人软件| 99re免费99re在线视频手机版| 亚洲AV成人一区二区三区观看| 亚洲精品无码午夜福利中文字幕| 日本亚洲免费无线码| 一级毛片成人免费看a| 亚洲黄色一级毛片| 亚洲av区一区二区三|