简体   繁体   English

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

[英]testing a delete method in jUnit using jdbcTemplate and DAO Layer

i'm trying to test my delete method but i don't know how can i do that, i tried inside my test delete method to invoke my searchByID with the id of the User i deleted to create a null variable and then use assertNull 我正在尝试测试我的删除方法,但我不知道该怎么做,我尝试在我的测试删除方法中调用我删除的用户ID的searchByID来创建一个空变量,然后使用assertNull

like this: 像这样:

    @Test
    public void deleteUser() 
    {

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

but this give me this error: 但这给了我这个错误:

expected null but was domain.User@c506pb

i tried to use the exception approach, since i can whatch in my output that that code generates a java.sql.SQLException: ORA-01403: no data found i tried like this : 我尝试使用异常方法,因为我可以在输出中该代码生成java.sql.SQLException: ORA-01403: no data found我这样尝试:

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

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

    }

but this give me this error: 但这给了我这个错误:

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

here is my delete method implementation 这是我的删除方法的实现

@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();
        }
    }
}

the method works since it deletes the correct user, i will like to do it using both approachs the exception approach and the other one, but i dont know why is not working 该方法有效,因为它删除了正确的用户,我想使用异常方法和另一种方法来做,但是我不知道为什么不起作用

EDIT: 编辑:

here is my searchById method 这是我的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;
    }

and here is my PL/SQL searchById 这是我的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;
/

and here is my delete PL/SQL 这是我的删除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;
/

EDIT 2 编辑2

i created this suggested method but it gives me a error that i'm missing a return value so i added return null 我创建了这个建议的方法,但它给了我一个错误,我缺少返回值,所以我添加了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;

        }
    });   
}

and when i run my unit test it says null pointer exception in this line 当我运行我的单元测试时,它在这一行说空指针异常

userDAO.deleteUserById(3); userDAO.deleteUserById(3);

EDIT 3 编辑3

i tried with this seting firts the user as null so if there's a exception my method returns a null object but still i have the same problem in my unit test when i try to use the exception approach 我尝试使用此设置将用户设置为null,因此如果出现异常,我的方法将返回null对象,但是当我尝试使用异常方法时,我的单元测试中仍然存在相同的问题

@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;
    }

here is my unit test that i expect to have a null value this works with the modfications i did 这是我的单元测试,我希望有一个空值,这可以与我所做的修改一起使用

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

but instead if i try to use the exception approach i have the following error 但是,如果我尝试使用异常方法,则会出现以下错误

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

this give me Expected exception: java.sql.SQLException java.lang.AssertionError 这给了我Expected exception: java.sql.SQLException java.lang.AssertionError

i dont know why this not work if i have the following exception in my output java.sql.SQLException: ORA-01403: no data found 我不知道为什么如果我的输出java.sql.SQLException: ORA-01403: no data found存在以下异常,这将不起作用java.sql.SQLException: ORA-01403: no data found

The problem lies in your method serachUserById(). 问题出在您的方法serachUserById()上。 I fixed it for you in the code bellow. 我在下面的代码中为您修复了该问题。 You always returned a user object. 您总是返回一个用户对象。 No matter if there was a user in the database or not. 无论数据库中是否有用户。 The code bellow first assigns null to the user. 下面的代码首先为用户分配null。 I guess there is an exception if there is no user with this userId. 我想如果没有使用该userId的用户,就会有一个例外。 So you catch the exception and continue returning null. 因此,您捕获了异常并继续返回null。 If there is a user in the DB you will create a User object, fill it with values and return that one. 如果数据库中有一个用户,则将创建一个User对象,将其填充值并返回该对象。

The key point is to distinguish between 1. There is a user and I return it with a User object and 2. There is not user and I return null. 关键是要区分1。有一个用户,我用User对象返回它; 2。没有用户,我返回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;
}

Anyway I would recommend you to work with spring jpa repositories instead of jdbc connections, SQL and stored procedures. 无论如何,我建议您使用Spring JPA存储库,而不要使用JDBC连接,SQL和存储过程。 You will save a lot of time and bugs. 您将节省大量时间和错误。

There could be below possibilities 可能存在以下可能性

  1. There is problem within your PL/SQL. 您的PL / SQL中有问题。 See when you are getting that exception? 看到何时收到该异常? While deleting user or while searching the user. 在删除用户或搜索用户时。

  2. What's the configuration value set for defaultRollback in your transaction configuration of the test context? 在测试上下文的事务配置中为defaultRollback设置的配置值是什么? If it is true that means your changes are getting rolled back after execution of test method and that's why you might be getting value in search user 如果确实如此,则意味着您的更改将在执行测试方法后回滚,这就是为什么您可能会在搜索用户中获得价值的原因

  3. If everything else is all-right then there might be issue with transaction boundaries. 如果其他一切都没问题,那么可能存在事务边界问题。

For starters I would suggest you rewrite your JDBC code and actually use the JdbcTemplate . 首先,我建议您重写JDBC代码并实际使用JdbcTemplate Instead of managing connections yourself, wrap your logic in a ConnectionCallback saves you from opening/closing a connection. 不用自己管理连接,而是将逻辑包装在ConnectionCallback可以避免打开/关闭连接。

Second for modifications you should use executeUpdate ins 其次,您应该使用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));

    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM