当前位置: 首页 > 图文教程 > 网络编程 > JSP > JBuilder2005单元测试之创建测试固件

JSP
我认为JSP有问题(上)
我认为JSP有问题(下)
jsp“抓”网页代码的程序
关于在bean里面打印html的利弊看法
bean里面如何打印到html页面
jdbc3中的RowSet 接口规范
Apusic Application Server1.0中jsp源代码泄漏漏洞
Unify的eWave ServletExec拒绝服务漏洞
通过提交超长的GET请求导致IBM HTTP Server远程溢出
在HTTP请求中添加特殊字符导致暴露JSP源代码文件
Resin 1.2 重要源代码暴露漏洞
多中WEB服务器的通用JSp源代码暴露漏洞
Tomcat 暴露JSP文件内容
IBM WebSphere Application Server 暴露JSP文件内容
JRun 2.3.x 范例文件暴露站点安全信息
BEA WebLogic 暴露源代码漏洞
IBM WebSphere Application Server 3.0.2 存在暴露源代码漏洞
Tomcat 3.1 存在暴露网站路径问题
Sun Java Web Server 能让攻击者远程执行任意命令
Netscape 修复 JAVA 安全漏洞

JSP 中的 JBuilder2005单元测试之创建测试固件


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 54 ::
收藏到网摘: n/a

在测试用例中通过setUp()、tearDown()创建测试固件,只能使这个测试固件在单个测试用例的不同测试方法中共用,如果有多个测试用例都需要使用相同的测试固件,就需要将测试固件抽取到一个独立的类中。JBuilder提供了3个预定义的测试固件类,它们分别是:
  ·JDBC测试固件(JDBC Fixture):用于获取数据库连接的测试固件,用户仅需要通过设置一些数据库信息,就可以用方便的方法获取数据连接。
  ·JNDI 测试固件(JNDI Fixture):用于模拟从JDNI环境中获取对象的测试固件。
  ·比较测试固件(Comparision Fixture):将测试输出到外部文件中,以便第二次测试时进行比较。
  ·自定义测试固件(Custom Fixture):用户自定义的测试固件。
  如果对JUnit的框架结构非常了解,也许这些JBuilder扩展的测试固件对你来说意义并不大,它们无非是构建一些常见的测试环境罢了,你完全可以自己编写。在本节里,我们介绍两个测试固件。
  JDBC测试固件

  如果你的工程中已经有一个获取数据连接的公共类,你也有必要构建一个JDBC测试固件,因为JDBC测试固件不但可以直接通过创建测试用例的向导直接指定,此外,JDBC测试固件还提供了许多面向测试的方法。
  为了创建JDBC测试固件,我们先创建一个JDataStore的数据库,其数据文件位于/db/hr.jds,这个数据库的用户名和密码是:sysdba/123456。hr.jds数据库中有一张EMPLOYEE的表,其结构如下所示:

  图 错误!文档中没有指定样式的文字。EMPLOYEE表的数据

  EMPLOYEE有3个字段,分别是ID、NAME和AGE,分别是String、String和int类型,并按上图所示填入3条记录。
  为了演示JDBC测试固件的具体使用,我们设计两个业务类:Employee和EmployeeDAO,尔后用JDBC测试固件为测试EmployeeDAO提供数据连接。这两个类的代码如下:
  代码清单 错误!文档中没有指定样式的文字。Employee.java类
  1. package chapter25.db;
  2. public class Employee
  3. {
  4.  private String id;
  5.  private String name;
  6.  private int age;
  7.  public Employee(String id, String name, int age) {
  8.   this.id = id;
  9.   this.name = name;
  10.  this.age = age;
  11.  }
  12.  public String getId() {
  13.   return id;
  14.  }
  15.  public String getName() {
  16.   return name;
  17.  }
  18.  public int getAge() {
  19.   return age;
  20.  }
  21.  public boolean equals(Object o) {
  22.   if (o instanceof Employee) {
  23.    Employee e1 = (Employee) o;
  24.    return id.equals(e1.getId()) && name.equals(e1.getName()) &&age == e1.getAge();
  25.   } else {
  26.    return false;
  27.   }
  28.  }
  29. }
  Employee类用于描述EMPLOYEE表的一条记录,该类访问数据库的EmployeeDAO代码如下所示:
  代码清单 错误!文档中没有指定样式的文字。EmployeeDAO.java类
  1. package chapter25.db;
  2. import java.sql.*;
  3. public class EmployeeDAO
  4. {
  5.  private Connection conn;
  6.  public EmployeeDAO(Connection conn) {
  7.   this.conn = conn;
  8.  }
  9.  public Employee findById(String id) throws SQLException
  10.  {
  11.   String sqlStr = "select * from employee where id ='"+id+"'";
  12.   Statement stat = conn.createStatement();
  13.   ResultSet rs = stat.executeQuery(sqlStr);
  14.   if (rs.next()) {
  15.    return new Employee(id,rs.getString("name"),rs.getInt("age"));
  16.   }else{
  17.    return null;
  18.   }
  19.  }
  20. }
  为了节省篇幅,我们仅提供一个访问数据库的访问方法:findById(),即通过id查找Employee对象。
  下面,我们利用JBuilder向导创建一个JDBC测试固件:
  1. File->New...->Test->在Test页中,双击JDBC Fixture图标,启动创建向导,其对话框如下所示:

  图 错误!文档中没有指定样式的文字。指定JDBC测试固件类名

在Class name中为JDBC测试固件指定类名:HrJdbcFixture,接受其他的默认设置,按Next到下一步。

2.设置连接数据库的信息。
在这步里,JBuilder提供了大部分数据库驱动程序的选择和连接信息设置,其对话框如下所示:


  图 错误!文档中没有指定样式的文字。指定数据库连接信息

  ·Driver:选择borland.databstore.jdbc.DataStoreDriver类。JDBC测试固件提供了对大多数数据库的支持。其中下拉框中暂不可用的数据库驱动器类显示为红色,你可以通过配置工程扩展类库使它们可用。
  ·URL:点击其后的…按钮,弹出Create URL for DataStore对话框,如下图所示:

  图 错误!文档中没有指定样式的文字。构造DataStore数据连接URL的对话框

  该对话框的设置内容会随着数据库类型的不同而变化。对于JDataStore数据库,该对话框提供了两个选项,如果数据库文件放在本机上时用第一个设置项,否则用第二个设置项。我们选择第一种选项,点击其后的…按钮,导航到/db/hr.jds并选择之,按OK返回向导主对话框窗口。
  ·User name:sysdba。
  ·Password:123456。
  按对话框下的Test Connection测试连接,应该会返回一个Success信息报告连接测试成功。按Finish创建JDBC 测试固件,其代码如下所示:
  代码清单 错误!文档中没有指定样式的文字。HrJdbcFixture.java

  1. package fixture;
  2. import java.sql.*;
  3. import java.io.*;
  4. import com.borland.jbuilder.unittest.JdbcFixture;
  5. public class HrJdbcFixture
  6. extends JdbcFixture
  7. {
  8.  public HrJdbcFixture(Object obj) {
  9.   super();
  10.  super.setUrl("jdbc:borland:dslocal:D:/JTJB2005/chapter25/db/hr.jds");
  11.  super.setDriver("com.borland.datastore.jdbc.DataStoreDriver");
  12.  super.setUsername("sysdba");
  13.  super.setPassword("123456");
  14. }
  15.
  16. public void setUp() {
  17.  super.setUp();
  18. }
  19.
  20. public void tearDown() {
  21.   super.tearDown();
  22.  }
  23. }

  JDBC测试固件承继了com.borland.jbuilder.unittest.JdbcFixture,这个类的重要方法包括:
  ·dumpResultSet():将一个ResultSet导到一个Writer中,该方法接受两个参数,一个是ResultSet另一个是Writer。
  ·getConnection():获取一个数据连接。
  ·runSqlBuffer():执行缓存于StringBuffer对象中的SQL语句。
  ·runSqlFile():执行保存在文件中的SQL语句,通过入参指定SQL文件的地址。
  ·setDriver():设置JDBC驱动器。
  ·setUrl():设置数据连接的URL。
  ·setUsername():设置用户名。
  ·setPassword():设置密码。
  提示:
  通过向导创建JDataStore的JDBC测试固件,虽然可以直接在对话框中选择com.borland.datastore.jdbc.DataStoreDriver驱动器,但运行这个JDBC测试固件时,JBuilder却报这样的错误信息:java.lang.ClassNotFoundException: com.borland.datastore.jdbc.DataStoreDriver。原来是JBuilder通过向导创建JDBC测试固件时,并没有直接将驱动器类加载到工程类库中,所以你需要手工通过Project->Project Properties...->Paths中,将JBuilder类库中名为JDataStore类库项加到工程类库中。
  由于EMPLOYEE表的数据可能会随着测试的进行不断更改,这样在测试时测试规则就很难制定,因为规则的制定必须基于一个假设的环境。举个例子,我们现在要测试findById()方法,就必须知道EMPLOYEE表中有哪些数据,所以在测试开始时就必须创建好一些特定的数据。由于JDBC固件可以执行保存在外部文件中的SQL,所以我们创建一个insert.sql文件,将其放置在/db/insert.sql下,文件的内容如下:

  delete from employee;insert into employee values('0004','大山',23);insert into employee values('0005','英华',30);insert into employee values('0006','柯明',31);

  运行这个SQL语句时,先清空EMPLOYEE表中的数据,然后再插入3条特定的记录。下面,我们来创建应用JDBC测试固件的TestEmployeeDAO测试用例类。
  1.在编辑器中激活EmployeeDAO。
  2.File->New...->Test->双击Test Case图标启动创建测试用例的向导,在向导第1、2步为EmployeeDAO的创建一个名为TestEmployeeDAO的测试用例,这个测试用例对EmployeeDAO的findById()方法进行功能测试。
  3.在向导的第3步选择测试固件,在向导对话框中我们前面创建的HrJdbcFixture已经出现在列表中。你也可以通过对话框的Add...和Remove选择不同的测试固件。


  图 错误!文档中没有指定样式的文字。选择测试固件

  按Finish直接创建TestEmployeeDAO的测试用例,其代码如下所示:
  代码清单 错误!文档中没有指定样式的文字。TestEmployeeDAO.java,向导创建的测试用例类
  1. package chapter25.db;
  2. import junit.framework.*;
  3. import fixture.*;
  4. import java.sql.*;
  5. public class TestEmployeeDAO extends TestCase {
  6.  private EmployeeDAO employeeDAO = null;
  7.  HrJdbcFixture hrJdbcFixture;
  8.  protected void setUp() throws Exception {
  9.   super.setUp();
  10.  /**@todo verify the constructors*/
  11.  employeeDAO = new EmployeeDAO(null);
  12.  hrJdbcFixture = new HrJdbcFixture(this);
  13.  hrJdbcFixture.setUp();
  14. }
  15.
  16. protected void tearDown() throws Exception {
  17.  employeeDAO = null;
  18.  hrJdbcFixture.tearDown();
  19.  hrJdbcFixture = null;
  20.  super.tearDown();
  21. }
  22.
  23. public void testFindById() throws SQLException {
  24.  String id = ";
  25.  Employee expectedReturn = null;
  26.  Employee actualReturn = employeeDAO.findById(id);
  27.  assertEquals("return value", expectedReturn, actualReturn);
  28.  /**@todo fill in the test code*/
  29. }
  30. }

  测试用例在setUp()方法中实例化HrJdbcFixture对象,并调用其setUp()方法初始化环境。只有JDBC测试固件的setUp()方法执行后(第13),才可调用JDBC测试固件的其他方法,如getConnection()等,所以JDBC测试固件的setUp()是其初始化方法。下面我们对这个TestEmployeeDAO进行改造,改造的代码如下粗体代码所示:
  代码清单 错误!文档中没有指定样式的文字。改造后的TestEmployeeDAO类

  1. …
  2. public class TestEmployeeDAO extends TestCase {
  3.  …
  4.  protected void setUp() throws Exception {
  5.   super.setUp();
  6.   hrJdbcFixture = new HrJdbcFixture(this);
  7.   hrJdbcFixture.setUp();
  8.   employeeDAO = new EmployeeDAO(hrJdbcFixture.getConnection());
  9.   hrJdbcFixture.runSqlFile("D:/JTJB2005/chapter25/db/insert.sql",true);
  10. }
  11. …
  12. public void testFindById() throws SQLException {
  13.  Employee expectEmp = new Employee("0004","大山",23);
  14.  Employee realEmp = employeeDAO.findById("0004");
  15.  assertNotNull(realEmp);
  16.  assertEquals(expectEmp,realEmp);
  17. }
  18. }

  因为JDBC测试固件需要在setUp()方法调用后,其他方法才可用,所以在TestEmployeeDAO的setUp()方法中,我们将EmployeeDAO的实例化方法移到后面,以便实例化EmployeeDAO时可以通过hrJdbcFixture.getConnection()获取数据连接(第8行)。在第9行,执行insert.sql文件,清除表中原来的数据并插入3行测试数据。
  在第13~14行,通过EmployeeDAO的findById()方法查找返回ID为0004的Employee对象,在第15~16行设定两个测试规则。
  运行这个带JDBC测试固件的测试用例,HrJbdcFixture测试固件先准备好测试环境,然后再执行TestEmployeeDAO的testFindById()测试方法。

   比较测试固件
  比较固件用于记录下当前的测试记录,以便和下一次的输出比较。比较固件类继承于com.borland.jbuilder.unittest.TestRecorder,而TestRecorder类继承java.io.Writer。所以如果在测试时,需要用Writer输出信息就可以考虑使用比较固件了,它提供了许多易用的输出信息的方法。你可以通过向导来创建比较固件。
  TestRecorder共有 4个记录模式的常量,它们分别是:
  ·UPDATE:比较固件将当前输出信息和已存在的信息文件相比较,如果文件没有存在则新创建一个文件,记录输出信息。
  ·COMPARE:比较固件将当前输出的信息和已经存在的信息比较。
  ·RECORD:比较固件记录当前输出的信息,如果原来已经有输出文件存在,覆盖之。
  ·OFF:关闭比较固件的功能。
  注意:
  在创建记录文件后,假设你更改了测试用例或测试套件,需要重新初始化这个输出文件:将TestRecorder的输出模式设置为RECORD,创建文件后再将其调整为UPDATE。输出的数据文件是二进制文件,放在和源程序文件相同的目录下且和测试用例类同名。
  下面是测试固件常用的方法,介绍如下:
  ·boolean print(String s)
  用TestRecorder打印一个字符串,如果模式为RECORD,且这个字符串和原来记录的不一致,则返回false。你可以设定这样的测试规则:
  assertTrue(recorder.print(result.toString())
  ·boolean println(String s)
  和print()相似,只不过添加一个换行。
  ·boolean compareObject(Object o)
  调用传入对象的equals()方法和用前面用recordObject()记录的对象进行比较。
  ·boolean recordObject()
  记录一个对象,以便后面调用compareObject()方法进行比较。
  下面,我们创建一个比较固件,并应用这个比较固件为Employee类创建一个测试用例。
  1.File->New...->Test->在Test页中,双击Comparision Fixture图标启动创建比较固件类的向导,其对话框如下所示:

  图 错误!文档中没有指定样式的文字。指定比较固件名及属性

  ·Class name:测试固件类名,接受默认的ComparisionFixture1。
  ·Echo output to console:测试固件将信息同时输出到测试运行器的控制台上。
  ·Verbose output:测试固件将输出详细的信息。
  此外,Save comparision data in this directory指定比较输出信息文件的存放位置,可以通过其后的…按钮更改,这里我们接受默认的设置。按OK直接创建比较固件类,你代码如下所示:
  代码清单 错误!文档中没有指定样式的文字。?15 ComparisonFixture1.java,向导创建的测试固件类
  1. package fixture;
  2. import com.borland.jbuilder.unittest.TestRecorder;
  3. public class ComparisonFixture1 extends TestRecorder
  4. {
  5.
  6.  public ComparisonFixture1(Object obj) {
  7.   super();
  8.   super.setMode(UPDATE);
  9.   super.setVerbose(true);
  10.  super.setEcho(true);
  11.  String fileName = super.constructFilename("D:/JTJB2005/chapter25/test",obj);
  12.  super.setOutputFile(fileName);
  13. }
  14.
  15. public void setUp() {
  16. }
  17.
  18. public void tearDown() {
  19. }
  20. }
  第8行将模式设置为UPDATE,而第9,10行对输出属性作设置。第11~12行指定输出文件的目录。
  2.创建TestEmployee测试用例类。
  File->New...->Test->在Test页,双击Test Case图标启动创建测试用例向导,为Employee类和构造函数创建TestEmployee测试用例类。在向导的第1步,你将看到如下的对话框:

  图 错误!文档中没有指定样式的文字。选择测试Employee类的构造函数

  点击Next一直到向导的第3步:     
  列表中列出了工程的所有的测试固件,选择HrJdbcFixture,点击Remove删除这个固件,只留下ComparisionFixture1的固件,点击Finish直接创建TestEmployee测试用例类的代码框架,在代码框架基础上利用比较固件对Employee进行测试,其最终代码如下所示:

  代码清单 错误!文档中没有指定样式的文字。应用比较固件的测试用例

  1. package chapter25.db;
  2.
  3. import junit.framework.*;
  4. import fixture.*;
  5.
  6. public class TestEmployee extends TestCase {
  7. private Employee employee = null;
  8. ComparisonFixture1 comparisonFixture1;
  9.
  10.  protected void setUp() throws Exception {
  11.   super.setUp();
  12.   employee = new Employee("0004", "王五", 23);
  13.   comparisonFixture1 = new ComparisonFixture1(this);
  14.   comparisonFixture1.setUp();
  15.  }
  16.
  17.  protected void tearDown() throws Exception {
  18.   employee = null;
  19.   comparisonFixture1.tearDown();
  20.   comparisonFixture1 = null;
  21.   super.tearDown();
  22.  }
  23.
  24.  public void testEmployee() {
  25.   String id = "0004";
  26.   String name = "王五";
  27.   int age = 23;
  28.   comparisonFixture1.print(employee.getId());
  29.   comparisonFixture1.recordObject(employee);
  30.   employee = new Employee(id, name, age);
  31.   assertTrue(comparisonFixture1.print(employee.getId()));
  32.   assertTrue(comparisonFixture1.compareObject(employee));
  33.  }
  34. }
  在第12行实例化一个Employee对象,在第28行保持并打印出原employee对象的id值,在第31行进行比较;第29行记录原employee对象,在第31行进行两对象的比较。
  运行TestEmployee类,在测试运行器的测试输出标签页中,你将可以看到输出的信息,在测试用例所在的文件夹下将创建一个无后缀名的输出文件Employee。