【问题标题】:how to test method with resultSet and preparedStatement如何使用 resultSet 和preparedStatement 测试方法
【发布时间】:2021-10-10 17:38:45
【问题描述】:

我想对我的方法进行单元测试,该方法从最后插入的对象的数据库 id 返回:

     public int getLastId() throws SQLException {
        String query = "select LAST_INSERT_ID();";
        PreparedStatement stmt = connection.prepareStatement(query);
        int id = -1;
        ResultSet resultSet = stmt.executeQuery();
        while (resultSet.next()) {
            id = resultSet.getInt("LAST_INSERT_ID()");
        }
        return id;
    }

然后我想像这样进行相同的单元测试:

    dataBaseService = mock(DataBaseService.class);
        resultSet = mock(ResultSet.class);

     @Test
    public void getLastIdIsCorrect() throws SQLException {
        //given
        int expectedId = 1;
        int expectedIncorrectId = 101;
        //when
        when(resultSet.getInt("LAST_INSERT_ID()")).thenReturn(1);
        when(dataBaseService.getLastId()).thenCallRealMethod();
        int result = dataBaseService.getLastId();
        //then
        Assert.assertEquals(expectedId, result);
        Assert.assertNotEquals(expectedIncorrectId, result);
    }

但是我得到空指针异常符合 PreparedStatement stmt = connection.prepareStatement(query);

您能否解释一下,如何正确地进行这样的单元测试?遇到同样问题的方法很少,我还在学习单元测试....

【问题讨论】:

    标签: unit-testing mocking mockito resultset


    【解决方案1】:

    问题是,您似乎不清楚自己在测试什么。如果您正在测试 getLastId 的代码,那么您不应该模拟包含它的类 - DataBaseService - 通常。相反,您的测试将是一个类似这样的对 DataBaseService 的测试......

    Connection connection = mock(Connection.class);
    PreparedStatement stmt = mock(PreparedStatement.class);
    

    ...和...

    when(connection.prepareStatement(Mockito.anyString())).thenReturn(stmt);
    when(stmt.executeQuery()).thenReturn(resultSet);
    

    当您在 DataBaseService 之外并想要测试调用它的东西时,您可以模拟 DataBaseService 并简单地返回一个数字。但是对于测试 DataBaseService 它不需要做类似...

    dataBaseService = mock(DataBaseService.class);
    ...
    when(dataBaseService.getLastId()).thenCallRealMethod();
    

    只需创建一个DataBaseService 的新实例并模拟它“内部”的东西,例如连接。

    要显示更多代码,需要知道您的类的设置以及您使用的 JUnit 版本。

    【讨论】:

    • 谢谢回答,我试图改变,现在我得到“通信链接故障”,就像我的回答一样......:/
    • 您可以静态模拟 DriverManager 但实际上这通常是个坏主意。有不同的方法可以做得更好,例如,您可以从外部进行连接。或者使用数据库连接池。没有你的代码很难说。
    【解决方案2】:

    好的,谢谢你的回答 :) 我已经更改并创建了 DataBaseService 对象,然后尝试像这样模拟里面的所有内容:

    @Test
    public void getLastIdIsCorrect() throws SQLException {
        //given
        int expectedId = 1;
        int expectedIncorrectId = 101;
        //when
        when(DriverManager.getConnection(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(connection);
        when(connection.prepareStatement(Mockito.anyString())).thenReturn(stmt);
        when(stmt.executeQuery()).thenReturn(resultSet);
        int result = dataBaseService.getLastId();
        //then
        Assert.assertEquals(expectedId, result);
        Assert.assertNotEquals(expectedIncorrectId, result);
    }
    

    现在我也遇到了这个异常和头痛 :D :

    com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
    

    【讨论】:

      猜你喜欢
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 2010-11-05
      • 1970-01-01
      相关资源
      最近更新 更多