<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 閱讀(226) 評論(0)  編輯  收藏 所屬分類: 數據庫

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

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲成av人在线观看网站| 18禁止看的免费污网站 | 78成人精品电影在线播放日韩精品电影一区亚洲 | 成人精品国产亚洲欧洲| 一级特黄特色的免费大片视频| 99视频在线看观免费| 日本免费一区尤物| 18gay台湾男同亚洲男同| 成人亚洲国产精品久久| 免费阿v网站在线观看g| 亚洲人成无码网站| 亚洲AV网一区二区三区| 免费做爰猛烈吃奶摸视频在线观看 | 亚洲AV午夜福利精品一区二区| 99久久亚洲精品无码毛片| 五月天国产成人AV免费观看| 精品久久香蕉国产线看观看亚洲| 亚洲精品自偷自拍无码| 免费H网站在线观看的| 日韩一卡2卡3卡4卡新区亚洲 | 四虎免费大片aⅴ入口| 亚洲欧洲日韩不卡| 久久精品无码免费不卡| 亚洲国产香蕉人人爽成AV片久久 | 亚洲国产精品久久网午夜| 毛片基地看看成人免费| 亚洲人成国产精品无码| 男女猛烈无遮掩视频免费软件| 成人免费无码大片A毛片抽搐 | 亚洲午夜爱爱香蕉片| 日本高清免费中文在线看| 亚洲高清成人一区二区三区 | 久久久久女教师免费一区| 日韩亚洲变态另类中文| 亚洲第一视频在线观看免费| 亚洲精品和日本精品| 日韩av无码免费播放| 亚洲丝袜美腿视频| 毛片在线免费视频| 久久久久亚洲国产AV麻豆| 亚洲成?Ⅴ人在线观看无码|