使用 jdbcTemplate 和 DAO 层在 jUnit 中测试删除方法

testing a delete method in jUnit using jdbcTemplate and DAO Layer

我正在尝试测试我的删除方法,但我不知道该怎么做,我尝试在我的测试删除方法中使用我删除的用户的 ID 调用我的 searchByID 以创建一个空变量然后使用 assertNull

像这样:

    @Test
    public void deleteUser() 
    {

        userDAO.deleteUserById(3);
        User nullUser  =  userDAO.searchUserById(3);
        assertNull(nullUser);
    }

但这给了我这个错误:

expected null but was domain.User@c506pb

我尝试使用异常方法,因为我可以在我的输出中发现该代码生成 java.sql.SQLException: ORA-01403: no data found 我这样试过:

    @Test(expected=SQLException.class)
    public void deleteUser() 
    {

         userDAO.deleteUserById(3);
        Usuario usuarioVacio  =  usuarioDAO.buscarUsuarioPorId(3);

    }

但这给了我这个错误:

Expected exception: java.sql.SQLException
java.lang.AssertionError

这是我的删除方法实现

@Override
public void deleteUserById(int idUser)
{

    Connection connection = null;
    try {

        String storedProcedure =  "{ call deleteUserById(?) }";

        connection  =  jdbcTemplate.getDataSource().getConnection();
        CallableStatement callableStatement = connection.prepareCall(storedProcedureBorrarUSuario);

        callableStatement.setInt(1, idUser);

        callableStatement.executeQuery();
    } 
    catch (SQLException ex) 
    {

        ex.printStackTrace();
    }
    finally 
    {
        if(connection != null)
        try 
        {
            connection.close();
        } 
        catch (SQLException e) 
        {
            e.printStackTrace();
        }
    }
}

该方法有效,因为它删除了正确的用户,我想使用异常方法和另一种方法来执行此操作,但我不知道为什么不起作用

编辑:

这是我的 searchById 方法

@Override
    public Usuario buscarUsuarioPorId(int userId) 
    {
        User user=  new  User();
        Connection connection = null;
        try {
            String storedProcedureInfoUsuario  =  "{ call searchUserById(?, ?, ?, ?, ?) }";

            connection  =  jdbcTemplate.getDataSource().getConnection();
            CallableStatement callableStatement = connection.prepareCall(storedProcedureInfoUsuario);

            callableStatement.setInt(1, idUsuario);
            callableStatement.registerOutParameter(2, Types.VARCHAR);
            callableStatement.registerOutParameter(3, Types.VARCHAR);
            callableStatement.registerOutParameter(4, Types.VARCHAR);
            callableStatement.registerOutParameter(5, Types.VARCHAR);

            callableStatement.executeQuery();

            //
            user.setName(callableStatement.getString(2));
            user.setLastName(callableStatement.getString(3));
            user.setEmail(callableStatement.getString(4));
            user.setState(callableStatement.getString(5));
        } 
        catch (SQLException ex) 
        {
//          Logger.getLogger(UsuarioDAOImplementacion.class.getName()).log(Level.SEVERE, null, ex);
            ex.printStackTrace();
        }
        finally 
        {
            if(connection != null)
            try 
            {
                connection.close();
            } 
            catch (SQLException e) 
            {
                e.printStackTrace();
            }
        }
        return usuario;
    }

这是我的 PL/SQL searchById

CREATE OR REPLACE PROCEDURE searchUserById
    (
       p_userId IN User.user_id%TYPE,
       ps_name OUT User.name%TYPE,
       ps_lastName OUT User.lastName%TYPE,
       ps_email OUT User.email%TYPE,
       ps_state OUT User.state%TYPE
    )
IS
BEGIN

  SELECT name, lastName, email, state
  INTO ps_name , ps_lastName , ps_email , ps_state 
  FROM  USER WHERE user_id= p_userid;

END;
/

这是我删除的 PL/SQL

CREATE OR REPLACE PROCEDURE deleteUserById
    (
       p_userId IN USER.user_ID%TYPE
    )
IS
BEGIN

  DELETE FROM USER
  WHERE user_id=p_userId;
COMMIT;
END;
/

编辑 2

我创建了这个建议的方法,但它给我一个错误,提示我缺少 return 值,所以我添加了 return null

 @Override
public void deleteUserById(final int idUser) {

    final String storedProcedureBorrarUSuario =  "{ call borrarUsuarioPorId(?) }";
    final Connection connection = null;

    jdbcTemplate.execute( new ConnectionCallback<Object>() 
    {
        @Override
        public Object doInConnection(Connection con) throws SQLException, DataAccessException 
        {
            CallableStatement callableStatement = connection.prepareCall(storedProcedureBorrarUSuario);
            callableStatement.setInt(1, idUser);
            callableStatement.executeUpdate();
            return null;

        }
    });   
}

当我 运行 我的单元测试时,它在这一行显示空指针异常

userDAO.deleteUserById(3);

编辑 3

我尝试使用此设置首先将用户设置为空,因此如果出现异常,我的方法 return 是一个空对象,但当我尝试使用异常方法时,我在单元测试中仍然遇到同样的问题

@Override
public Usuario searchUserById(int userId) 
{
    User user=  null;
    Connection connection = null;

    try {
        String storedProcedureInfoUsuario  =  "{ call searchUserById(?, ?, ?, ?, ?) }";

        connection  =  jdbcTemplate.getDataSource().getConnection();
        CallableStatement callableStatement = connection.prepareCall(storedProcedureInfoUsuario);

        callableStatement.setInt(1, userId);
        callableStatement.registerOutParameter(2, Types.VARCHAR);
        callableStatement.registerOutParameter(3, Types.VARCHAR);
        callableStatement.registerOutParameter(4, Types.VARCHAR);
        callableStatement.registerOutParameter(5, Types.VARCHAR);

        callableStatement.executeQuery();

        //
        user=  new User();
        usuario.setName(callableStatement.getString(2));
        usuario.setLastName(callableStatement.getString(3));
        usuario.setEmail(callableStatement.getString(4));
        usuario.setState(callableStatement.getString(5));
    } 
    catch (SQLException ex) 
    {
//          Logger.getLogger(UsuarioDAOImplementacion.class.getName()).log(Level.SEVERE, null, ex);
            ex.printStackTrace();
        }
        finally 
        {
            if(connection != null)
            try 
            {
                connection.close();
            } 
            catch (SQLException e) 
            {
                e.printStackTrace();
            }
        }
        return user;
    }

这是我的单元测试,我希望它有一个空值,这适用于我所做的修改

public void findUserById()
{
    User emptyUser=  userDAO.searchUserById(50);
    assertNull(emptyUser);
}

但如果我尝试使用异常方法,则会出现以下错误

@Test(expected=SQLException.class) 
public void findUserById()
    {
        User emptyUser=  userDAO.searchUserById(50);
        assertNull(emptyUser);
    }

这个给我Expected exception: java.sql.SQLException java.lang.AssertionError

如果我的输出中有以下异常,我不知道为什么这不起作用 java.sql.SQLException: ORA-01403: no data found

问题出在你的serachUserById()方法上。我在下面的代码中为您修复了它。您总是 returned 一个用户对象。不管数据库中是否有用户。下面的代码首先将 null 分配给用户。我想如果没有这个 userId 的用户会出现异常。所以你捕获异常并继续returning null。如果数据库中有用户,您将创建一个用户对象,用值填充它,然后 return 那个。

重点在于区分 1. 有一个用户,我 return 它有一个用户对象,并且 2.没有用户和我 return null.

@Override
public User serachUserById(int userId) 
{
    User user = null;
    Connection connection = null;
    try {
        String storedProcedureInfoUsuario  =  "{ call searchUserById(?, ?, ?, ?, ?) }";

        connection  =  jdbcTemplate.getDataSource().getConnection();
        CallableStatement callableStatement = connection.prepareCall(storedProcedureInfoUsuario);

        callableStatement.setInt(1, userId);
        callableStatement.registerOutParameter(2, Types.VARCHAR);
        callableStatement.registerOutParameter(3, Types.VARCHAR);
        callableStatement.registerOutParameter(4, Types.VARCHAR);
        callableStatement.registerOutParameter(5, Types.VARCHAR);

        callableStatement.executeQuery();

        //
        user = new User();
        user.setName(callableStatement.getString(2));
        user.setLastName(callableStatement.getString(3));
        user.setEmail(callableStatement.getString(4));
        user.setState(callableStatement.getString(5));
    } 
    catch (SQLException ex) 
    {

Logger.getLogger(UsuarioDAOImplementacion.class.getName()).log(Level.SEVERE, null, ex);
        ex.printStackTrace();
    }
    finally 
    {
        if(connection != null)
        try 
        {
            connection.close();
        } 
        catch (SQLException e) 
        {
            e.printStackTrace();
        }
    }
    return user;
}

无论如何,我建议您使用 spring jpa 存储库,而不是 jdbc 连接、SQL 和存储过程。您将节省大量时间和错误。

可能有以下几种可能

  1. 您的 PL/SQL 有问题。 看看你什么时候得到那个例外?删除用户或搜索用户时。

  2. 你在测试上下文的事务配置中为defaultRollback设置的配置值是多少?如果这是真的,这意味着您的更改在执行测试方法后将被回滚,这就是为什么您可能在搜索用户

  3. 中获得价值
  4. 如果其他一切正常,则可能是事务边界有问题。

对于初学者,我建议您重写 JDBC 代码并实际使用 JdbcTemplate。与其自己管理连接,不如将逻辑包装在 ConnectionCallback 中,从而避免 opening/closing 连接。

第二个修改你应该使用 executeUpdate ins

@Override
public void deleteUserById(final int idUser) {
    final String storedProcedure =  "{ call deleteUserById(?) }";
    getJdbcTemplate().execute(new ConnectionCallback<Object>() {
        public Object doInConnection(Connection con) throws SQLException, DataAccessException {
            CallableStatement callableStatement = con.prepareCall(storedProcedureBorrarUSuario);
            callableStatement.setInt(1, idUser);
            callableStatement.executeUpdate();
            return null;
        }
    });   
}

@Override
public Usuario buscarUsuarioPorId(final int userId) {       
    User user=  new  User();
    final String storedProcedureInfoUsuario  =  "{ call searchUserById(?, ?, ?, ?, ?) }";
    return getJdbcTemplate().execute(new ConnectionCallback<User>() {
        public User doInConnection(Connection con) throws SQLException, DataAccessException {
        CallableStatement callableStatement = con.prepareCall(storedProcedureInfoUsuario);

        callableStatement.setInt(1, idUsuario);
        callableStatement.registerOutParameter(2, Types.VARCHAR);
        callableStatement.registerOutParameter(3, Types.VARCHAR);
        callableStatement.registerOutParameter(4, Types.VARCHAR);
        callableStatement.registerOutParameter(5, Types.VARCHAR);

        callableStatement.executeQuery();
        //
        user.setName(callableStatement.getString(2));
        user.setLastName(callableStatement.getString(3));
        user.setEmail(callableStatement.getString(4));
        user.setState(callableStatement.getString(5));

    });
}