亚洲好骚综合-亚洲黄色录像-亚洲黄色网址-亚洲黄色网址大全-99久久99久久-99久久99久久精品国产

您的位置:軟件測(cè)試 > 開(kāi)源軟件測(cè)試 > 開(kāi)源單元測(cè)試工具 >
對(duì)DAO編寫(xiě)單元測(cè)試
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/2/19 15:12:51 ] 推薦標(biāo)簽:

  下面,我們開(kāi)始對(duì)DAO組件編寫(xiě)單元測(cè)試。前面提到了HSQLDB這一小巧的純Java數(shù)據(jù)庫(kù)。HSQLDB除了提供完整的JDBC驅(qū)動(dòng)以及事務(wù)支持外,HSQLDB還提供了進(jìn)程外模式(與普通數(shù)據(jù)庫(kù)類似)和進(jìn)程內(nèi)模式(In-Process),以及文件和內(nèi)存兩種存儲(chǔ)模式。我們將HSQLDB設(shè)定為進(jìn)程內(nèi)模式及僅使用內(nèi)存存儲(chǔ),這樣,在運(yùn)行JUnit測(cè)試時(shí),可以直接在測(cè)試代碼中啟動(dòng)HSQLDB。測(cè)試完畢后,由于測(cè)試數(shù)據(jù)并沒(méi)有保存在文件上,因此,不必清理數(shù)據(jù)庫(kù)。

  此外,為了執(zhí)行批量測(cè)試,在每個(gè)獨(dú)立的DAO單元測(cè)試運(yùn)行前,我們都執(zhí)行一個(gè)初始化腳本,重新建立所有的表。該初始化腳本是通過(guò)HibernateTool自動(dòng)生成的,稍后我們還會(huì)討論。下圖是單元測(cè)試的執(zhí)行順序:
對(duì)DAO編寫(xiě)單元測(cè)試 圖-2

  在編寫(xiě)測(cè)試類之前,我們首先準(zhǔn)備了一個(gè)TransactionCallback抽象類,該類通過(guò)Template模式將DAO調(diào)用代碼通過(guò)事務(wù)包裝起來(lái):

 public abstract class TransactionCallback {

  public final Object  execute() throws Exception {

  Transaction tx =  HibernateUtil.getCurrentSession().beginTransaction();

  try {

  Object r =  doInTransaction();

  tx.commit();

  return r;

  }

  catch(Exception e) {

  tx.rollback();

  throw e;

  }

  }

  // 模板方法:

  protected abstract Object  doInTransaction() throws Exception;

  }
 

  其原理是使用JDK提供的動(dòng)態(tài)代理。由于JDK的動(dòng)態(tài)代理只能對(duì)接口代理,因此,要求DAO組件必須實(shí)現(xiàn)接口。如果只有具體的實(shí)現(xiàn)類,則只能考慮CGLIB之類的第三方庫(kù),在此我們不作更多討論。

  下面我們需要編寫(xiě)DatabaseFixture,負(fù)責(zé)啟動(dòng)HSQLDB數(shù)據(jù)庫(kù),并在@Before方法中初始化數(shù)據(jù)庫(kù)表。該DatabaseFixture可以在所有的DAO組件的單元測(cè)試類中復(fù)用:

 public class DatabaseFixture {

  private static Server  server = null; // 持有HSQLDB的實(shí)例

  private static final  String DATABASE_NAME = "javaeedev"; // 數(shù)據(jù)庫(kù)名稱

  private static final  String SCHEMA_FILE = "schema.sql"; // 數(shù)據(jù)庫(kù)初始化腳本

  private static final  List<String> initSqls = new ArrayList<String>();
 @BeforeClass // 啟動(dòng)HSQLDB數(shù)據(jù)庫(kù)

  public static void  startDatabase() throws Exception {

  if(server!=null)

  return;

  server = new  Server();

  server.setDatabaseName(0,  DATABASE_NAME);

  server.setDatabasePath(0, "mem:" + DATABASE_NAME);

  server.setSilent(true);

  server.start();

  try {

  Class.forName("org.hsqldb.jdbcDriver");

  }

  catch(ClassNotFoundException cnfe) {

  throw new  RuntimeException(cnfe);

  }

  LineNumberReader  reader = null;

  try {

  reader = new  LineNumberReader(new     InputStreamReader(DatabaseFixture.class.getClassLoader().getResourceAsStream(SCHEMA_FILE)));

  for(;;) {

  String line =  reader.readLine();

  if(line==null) break;

  // 將text類型的字段改為varchar(2000),因?yàn)镠SQLDB不支持text:

  line =  line.trim().replace(" text ", " varchar(2000)  ").replace("  text,", " varchar(2000),");

  if(!line.equals(""))

  initSqls.add(line);

  }

  }

  catch(IOException e)  {

  throw new  RuntimeException(e);

  }

  finally {

  if(reader!=null)  {

  try {  reader.close(); } catch(IOException e) {}

  }

  }

  }
 @Before // 執(zhí)行初始化腳本

  public void initTables()  {

  for(String sql :  initSqls) {

  executeSQL(sql);

  }

  }
static Connection  getConnection() throws SQLException {

  return  DriverManager.getConnection("jdbc:hsqldb:mem:" + DATABASE_NAME,  "sa", "");

  }
static void  close(Statement stmt) {

  if(stmt!=null) {

  try {

  stmt.close();

  }

  catch(SQLException e) {}

  }

  }
static void  close(Connection conn) {

  if(conn!=null) {

  try {

  conn.close();

  }

  catch(SQLException e) {}

  }

  }
static void  executeSQL(String sql) {

  Connection conn =  null;

  Statement stmt =  null;

  try {

  conn =  getConnection();

  boolean  autoCommit = conn.getAutoCommit();

  conn.setAutoCommit(true);

  stmt = conn.createStatement();

  stmt.execute(sql);

  conn.setAutoCommit(autoCommit);

  }

  catch(SQLException e)  {

  log.warn("Execute failed: " + sql + "nException: "  + e.getMessage());

  }

  finally {

  close(stmt);

  close(conn);

  }

  }
public static Object  createProxy(final Object target) {

  return  Proxy.newProxyInstance(

  target.getClass().getClassLoader(),

  target.getClass().getInterfaces(),

  new  InvocationHandler() {

  public  Object invoke(Object proxy, final Method method, final Object[] args) throws  Throwable {

  return new TransactionCallback() {

  @Override

  protected Object doInTransaction() throws Exception {

  return method.invoke(target, args);

  }

  }.execute();

  }

  }

  );

  }

  }

上一頁(yè)1234下一頁(yè)
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠(chéng)聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd
主站蜘蛛池模板: 最近手机中文在线视频 | 黄色欧美在线观看 | 成人在线不卡 | 97狠狠干 | 怡红院美国十次成人影院 | 中文亚洲字幕 | 中文亚洲日韩欧美 | 刺激花蒂抽搐视频在线看 | 日本三级全黄三级三级三级口周 | 欧美视频不卡一区二区三区 | 国产一级黄色 | 午夜想想爱午夜剧场 | 黄色小视屏 | 亚洲丶国产丶欧美一区二区三区 | 精品亚洲成a人片在线观看 精品亚洲成a人在线播放 | 久久天天躁夜夜躁狠狠85麻豆 | 国产美女在线一区二区三区 | nu77亚洲综合日韩精品 | www.黄色片.com | 午夜影院免费 | 天天狠狠 | 香蕉乱码成人久久天堂爱免费 | 成人短视频在线免费观看 | 国产精品成人观看视频免费 | 香港国产特级一级毛片 | 日本免费新一区二区三区 | 一级级黄 | 欧美日韩国产在线 | 深夜免费网站 | 男女日批在线观看 | 亚洲人成网男女大片在线播放 | 九九九在线视频 | 国产一级特黄毛片 | 午夜网站在线 | 欧美日韩高清在线观看 | 中国男女全黄大片一级 | 欧美成人hd | 中文在线最新版天堂 | 波多野结衣在线中文字幕 | 高清无遮挡在线观看 | 精品国产欧美一区二区最新 |