【问题标题】:Testing jdbc queries and prepared statements测试 jdbc 查询和准备好的语句
【发布时间】:2018-02-18 21:00:29
【问题描述】:

我有一个类,我使用写 url 和获取连接的旧 jdbc 方法创建了与 h2 数据库的连接,并且我正在数据库中创建一个表,这是表不是 java 对象,所以我用完了为我的方法编写测试的聪明方法 这是其中一种方法

//above would be the url and driver connection

//我还创建了一个表 app_user 公共无效添加用户(连接连接, 字符串登录,字符串密码, 字符串描述)抛出 SQLException {

        System.out.println(String.format("Add user : %s", login));

        String newUSer = "INSERT INTO app_user(login, password, description) VALUES (?,?,?)";

        try (PreparedStatement preparedStatement = connection.prepareStatement(newUSer)) {

            preparedStatement.setString(1, login);
            preparedStatement.setString(2, password);
            preparedStatement.setString(3, description);

            // returns number of changed column
            preparedStatement.executeUpdate();
        }
    }

我的测试方法看起来像这样,有什么办法让它不那么整洁和更简单,我试图用 mockito 模拟,但我的 app_user 表不是 App_user 类的对象,所以我写了这个

@Test
    public void addUser() throws SQLException, ClassNotFoundException {


        Class.forName("org.h2.Driver");
        try (Connection connection = DriverManager.getConnection(URL, "sa", "")) {

            String createTable =
                    "CREATE TABLE app_user(" +
                            "user_id INT NOT NULL AUTO_INCREMENT," +
                            "login VARCHAR (255) NOT NULL ," +
                            "password VARCHAR (255) NOT NULL ," +
                            "description VARCHAR (255) NULL," +
                            "PRIMARY KEY (user_id))";

            try (Statement statement = connection.createStatement()) {
                statement.executeUpdate(createTable);
                Assert.assertNotNull(statement);
            }

            String addUser = "INSERT INTO app_user(login, password, description) VALUES (1234,'valentine','javaMan')";
            PreparedStatement statement = connection.prepareStatement(addUser);
            int rowAffected = statement.executeUpdate();

            Assert.assertNotNull(rowAffected);
            Assert.assertEquals(rowAffected,1);
        }

但我不喜欢在我的测试中我再次创建连接的事实,注意-由于某种原因我不能将对象用作表

【问题讨论】:

    标签: java unit-testing jdbc


    【解决方案1】:

    我个人发现的最好方法是创建一个静态类TestUtils,并添加一个静态方法来打开和查询数据库,以及另一个关闭连接的方法。连接本身是该类的成员。要搜索的SQL查询是字符串参数,ResultSet是要返回的值。

    下面是类。

    public class TestUtils {
        private static Connection conn = null;
        private static java.sql.Statement stmt = null;
        private static ResultSet rs;
    
        public static ResultSet readDB(String sql) throws ClassNotFoundException, SQLException {
            //lettura ladder da db insieme a configs
            // JDBC driver name and database URL
            final String DB_URL = "jdbc:mysql://localhost/sportservicelive";
    
            //  Database credentials
            final String USER = "root";
            final String PASS = "root";
    
            //STEP 2: Register JDBC driver
            Class.forName("com.mysql.jdbc.Driver");
    
            //STEP 3: Open a connection
    
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
    
            //STEP 4: Execute a query
    
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
    
            return rs;
        }
    
        public static void closeDB() throws SQLException {
            stmt.close();
            conn.close();
            rs.close();
        }
        [...]
    }
    

    当然,它还包含对单元测试有用的各种其他方法。

    【讨论】:

      【解决方案2】:

      就创建 JDBC 连接而言,我认为有一种优雅的方法可以最大程度地减少您的工作量。 我建议不要每次都创建一个连接,而是编写一个代表 JDBC 连接的单例类。这将避免您一遍又一遍地做的一些工作。

      类似于以下代码的内容。 (跳过例外和更多细节)

      class Database{
          Connection jdbc;
          //Can store username, url , password etc as private fields here
          private Database(){
              if(jdbc == null){
                  Class.forName("org.h2.Driver");
                  jdbc = DriverManager.getConnection("URL", "sa", "");
              }
          }
          Connection getConnection(){
              if(jdbc == null){
                  this();
              }
              return jdbc;
          }
      };
      

      【讨论】:

      • 你能展示一下它的外观吗,我知道一个单例类但从未使用过这种模式@Ashutosh 谢谢
      • @valik 我添加了代码 sn-ps 以供参考,希望对您有所帮助。
      • 这个单例类应该在我的测试类@Ashutosh 或单独的类中
      • 您可以将此单例类放在单独的类或包中,并在需要时使用它的方法。这才是重点。另外,如果有帮助的话,如果您能对答案进行投票,那就太好了。谢谢。
      • 我无法访问该方法,这是我尝试过的,Database db = Database.getInstance();还尝试使用 "new" ,然后在 db 类本身中添加了类的实例化,但没有 @Ashutosh
      猜你喜欢
      • 1970-01-01
      • 2013-08-02
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多