欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL学习笔记 09 - 封装JDBC和单元测试

程序员文章站 2022-05-09 13:15:37
...

一、封装JDBC

1、executeUpdate方法

添加删除修改的例子中,变化的数据只有SQL语句,其余的代码都是重复的,因此将重复代码封装到一个方法中,变化的数据定义为方法参数。为此我们定义一个专门用于执行增删改的方法executeUpdate,方法定义如下:

int executeUpdate(String sql,Object …values)

说明:

  1. 方法参数sql是要执行的insertupdatedelete语句。
  2. 方法可变参数valuesinsertupdatedelete语句中占位符
  3. sqlvalues这两个参数从外界传入,即外界传入什么样的SQL语句,executeUpdate()方法就执行什么样的SQL语句。
  4. 返回值int表示SQL语句执行后影响的行数

2、executeQuery方法

在查询的例子中,每次查询的SQL语句不同,为此我们定义一个专门用于执行查询的方法executeQuery,方法定义如下:

ResultSet executeQuery(String sql,Object …values) 

说明:

  1. 方法参数sql是要执行的select语句。
  2. 方法可变参数values是SQL语句中占位符的值
  3. sqlvalues这两个参数从外界传入,即外界传入什么样的SQL,executeQuery方法就 执行什么样的SQL语句。
  4. 返回值ResultSet表示SQL语句执行查询后的查询结果集。

3、封装JDBC

executeUpdate(String sql,Object …values)方法和executeQuery(String sql, Object … values )中都需要将values的值赋给sql语句中占位符?,因此将这两个方法中为占位符?赋值的代码抽象出来,定义为void setParameter(Object …values)方法。
executeUpdate(String sql,Object …values)方法和executeQuery(String sql, Object … values)中都需要连接数据库关闭资源,因此将这两个方法中连接数据库的代码抽象出来,封装成getConnection()方法,用于连接数据库,将关闭资源的代码抽象出来,封装成close()方法,用于关闭资源。
Connection对象、PreparedStatement对象、ResultSet对象、连接字符串定义为类的属性,由于这些属性不允许外界访问,因此将其定义为私有
由于该类是专门执行SQL语句的类,因此我们称它为DBHelper类。
实例:

import java.sql.*;

/**
 * 数据库访问助手
 *
 * @author DingYi
 * @date 2020/5/2 15:10
 */
public class DBHelper {

  // 数据库连接
  private Connection conn = null;
  // 语句
  private PreparedStatement ps = null;
  // 结果集
  private ResultSet rs = null;
  // 连接URL
  private static final String URL = "jdbc:mysql://localhost:3306/user_manager?useSSL=false&characterEncoding=utf8";
  // 用户名
  private static final String USER = "root";
  // 密码
  private static final String PASS = "root";


  // 1.加载驱动
  //加载驱动只需做一遍,故可以写在静态代码块中
  static {
    try {
      Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }

  // 2. 获得连接
  private void getConnection() throws SQLException {
    if(conn == null || conn.isClosed()){
      conn = DriverManager.getConnection(URL,USER,PASS);
    }
  }

  // 为占位符?赋值
  private void setParameter(Object ... values) throws SQLException {
    if(values != null && values.length > 0){
      for(int i = 0; i < values.length; i ++) {
        ps.setObject(i + 1, values[i]);
      }
    }
  }

  /**
   * 执行增删改的方法
   * @param sql 要执行的sql语句
   * @param values sql语句中?占位符的值
   * @return 执行结果
   * @throws SQLException sql异常
   */
  public int executeUpdate(String sql, Object ... values) throws SQLException {
    // 获得连接
    getConnection();
    // 创建语句
    ps = conn.prepareStatement(sql);
    // 为占位符?赋值
    setParameter(values);
    // 执行sql语句
    return ps.executeUpdate();
  }

  /**
   * 执行查询的sql语句
   * @param sql 要执行的sql语句
   * @param values sql语句中?占位符的值
   * @return 查询结果
   * @throws SQLException sql异常
   */
  public ResultSet executeQuery(String sql, Object ... values) throws SQLException {
    // 获得连接
    getConnection();
    // 创建语句
    ps = conn.prepareStatement(sql);
    // 为占位符?赋值
    setParameter(values);
    // 执行查询
    rs = ps.executeQuery();
    return rs;
  }

  // 6. 关闭资源
  public void close() throws SQLException {
    if(rs != null){
      rs.close();
      rs = null;
    }
    if(ps != null){
      ps.close();
      ps = null;
    }
    if(conn != null){
      conn.close();
      conn = null;
    }
  }
}

二、单元测试

1、单元测试

软件开发完成后,难免有bug存在(软件的缺陷称为bug),为了减少或避免bug,就必须对软件进行测试,发现bug后对bug进行修复,使得软件具有很好的稳定性健壮性
软件测试分为单元测试模块测试集成测试。通常模块测试集成测试测试工程师的职责,单元测试通常是开发工程师的职责。
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,在Java中单元指一个或者一个方法。通常使用JUnit单元测试工具对Java进行单元测试。
测试过程:

  1. 导入必要的包
    单元测试的类和注解位于JUnit4框架的org.junit包中,因此需要导入org.junit.*。断言类Assert的断言方法assertEquals静态方法,使用静态导入import static org.junit.Assert.*后在单元测试类中可以直接使用Assert类的静态方法进行断言。
  2. 测试类的定义
    测试类CalculatorTest是一个独立的类,没有显示继承任何父类。测试类的名字也可以任意命名没有任何局限性。所以我们不能通过类的声明来判断它是不是一个测试类,它与普通类的区别在于它内部方法声明
  3. 创建待测试的对象
    要测试哪个类,首先就要创建一个该类的对象,如:
private static Calculator calculator = new Calculator();

在单元测试中,方法上标注了@Test后,表明该方法是单元测试方法。除了@Test注解外,还有一些重要的注解,其作用如下表所示:

注解 解释 示例
@Test 标注在方法上,表明这是一个测试方法,返回值必须为void,而且不能有任何参数。 @Test
public void test() {
}
@Before 在任何一个测试执行之前必须执行的代码 @Before
public void setUp() throws Exception {
}
@After 在任何测试执行之后需要进行的收尾工作 @After
public void tearDown () throws Exception {
}
@BeforeClass 1:针对所有测试
2:只在测试用例初始化时执行一次
3:每个测试类只能有一个方法被标注为@BeforeClass
4:该方法必须是publicstatic
@BeforeClass
public static void beforeClass() {
}
@AfterClass 1:针对所有测试
2:只在测试用例执行结束时执行一次
3:每个测试类只能有一个方法被标注为@AfterClass
4:该方法必须是publicstatic 的。
@ AfterClass
public static void AfterClass() {
}
@Ignore 忽略的测试方法

一个JUnit4的单元测试用例执行顺序为:
MySQL学习笔记 09 - 封装JDBC和单元测试注意:

  1. 需要的jar包

hamcrest-core-1.3.jar
junit-4.12.jar

  1. 在进行单元测试时,需要把相应地Package导入进来。最主要的Packageorg.junit.*。 该包中包含了单元测试需要的绝大多数类;还需要导入import static org.junit.Assert.*, 其中包含了许多断言断言帮助我们判断测试的结果

2、测试用例

测试用例Test Case)是为某个特殊目标而编制的一组测试输入执行条件以及预期结果,以便测试某个程序路径或核实是否满足某个特定需求。测试之前应先编写测试用例,根据测试用例进行测试,并记录测试结果。下表是测试用例:
MySQL学习笔记 09 - 封装JDBC和单元测试
说明:

  1. 桩模块:是指模拟被测试的模块所调用的模块
  2. 测试状态:P指通过 F指失败

实例:
创建功能类

/**
 * 功能类
 *
 * @author DingYi
 * @date 2020/5/2 21:50
 */
public class Calculator {
  private static int result = 0; // 静态变量,用户存储计算结果

  public void add (int n) {
    result = result + n;
  }

  public void substract(int n) {
    // result = result - n;
    result = result - 1;
  }

  public void multiply(int n) {
    // result = result * n;
    // TODO 待开发
  }

  public void divide(int n) {
    result = result / n;
  }

  public void clear() {
    result = 0;
  }

  public int getResult() {
    return result;
  }
}

测试类:

import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.*;
/**
 * 测试类
 *
 * @author DingYi
 * @date 2020/5/2 21:57
 */
public class CalculatorTest {
  private static Calculator calculator = new Calculator();

  @Before
  public void setUp() throws Exception {
    calculator.clear();
  }

  @After
  public void tearDown() throws Exception {
    calculator.clear();
  }


  @Test
  public void add() {
    calculator.add(2);
    calculator.add(3);
    assertEquals(5, calculator.getResult());
  }

  @Test
  public void substract() {
    calculator.add(10);
    calculator.substract(2);
    assertEquals(8, calculator.getResult());
  }

  @Ignore("乘法还没有开发呢,暂时不需要测试")
  @Test
  public void multiply() {
  }

  @Test
  public void divide() {
    calculator.add(8);
    calculator.divide(2);
    assertEquals(4, calculator.getResult());
  }
}