【问题标题】:How do I test DAO using Mockito?如何使用 Mockito 测试 DAO?
【发布时间】:2019-07-01 07:23:02
【问题描述】:

我是单元测试的新手,我正在尝试为我的 DAO 编写一些测试。我在这里遵循了一些教程/答案,但其中大多数不适用于我的 DAO。

我在运行测试时收到此警告 org.mockito.exceptions.verification.WantedButNotInvoked: 通缉但未调用: mockConn.prepareStatement();

怎么了?

private ApprovalConditionDAO approvalConditionDAO;
@Mock
DataSource mockDataSource;
@Mock
Connection mockConn;
@Mock
PreparedStatement mockPreparedStmnt;
@Mock
CallableStatement cs;
@Mock
ResultSet mockResultSet;

@Before
public void setUp() throws SQLException {
    approvalConditionDAO = new ApprovalConditionDAO();
    when(mockDataSource.getConnection()).thenReturn(mockConn);
    when(mockDataSource.getConnection(anyString(),
                                      anyString())).thenReturn(mockConn);
    when(mockConn.prepareStatement(anyString(),
                                   anyInt())).thenReturn(mockPreparedStmnt);
    doNothing().when(mockConn).commit();
    doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
    when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
    when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
    when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
}

@Test
public void testCreateWithNoExceptions() throws SQLException {    
   ArrayList<ApprovalConditionBean> actualValues = approvalConditionDAO.getAllApprovalCondition();

    //verify and assert
    verify(mockConn, times(1)).prepareStatement(anyString());
    verify(mockPreparedStmnt, times(1)).execute();
    verify(mockConn, times(1)).commit();
    verify(mockResultSet, times(2)).next();
    verify(mockResultSet, times(1)).getString("ID");
    verify(mockResultSet, times(1)).getString("EIT_CODE");
    verify(mockResultSet, times(1)).getString("FRIST_KEY_TYPE");
    verify(mockResultSet, times(1)).getString("FRIST_KEY_VALUE");
    verify(mockResultSet, times(1)).getString("FRIST_EIT_SEGMENT");
    verify(mockResultSet, times(1)).getString("OPERATION");
    verify(mockResultSet, times(1)).getString("SECOND_KEY_TYPE");
    verify(mockResultSet, times(1)).getString("SECOND_KEY_VALUE");
    verify(mockResultSet, times(1)).getString("SECOND_EIT_SEGMENT");
    verify(mockResultSet, times(1)).getString("APPROVAL_CODE");
}

这就是我要测试的道。

  public class ApprovalConditionDAO extends AppsproConnection {
Connection connection;
PreparedStatement ps;
CallableStatement cs;
ResultSet rs;
RestHelper rh = new RestHelper();


public ArrayList<ApprovalConditionBean> getAllApprovalCondition() {

 ArrayList<ApprovalConditionBean> approvalConditionList =
     new ArrayList<ApprovalConditionBean>();
 try {
     connection = AppsproConnection.getConnection();
     String query =
         "SELECT * FROM "+" "+getSchema_Name()+".XXX_APPROVAL_CONDITION";
     ps = connection.prepareStatement(query);
     rs = ps.executeQuery();
     while (rs.next()) {
         ApprovalConditionBean approvalConditionBean = new ApprovalConditionBean();
         approvalConditionBean.setId(rs.getString("ID"));
         approvalConditionBean.setEitCode(rs.getString("EIT_CODE"));
         approvalConditionBean.setFirstKeyType(rs.getString("FRIST_KEY_TYPE"));
         approvalConditionBean.setFirstKeyValue(rs.getString("FRIST_KEY_VALUE"));
         approvalConditionBean.setFirstEitSegment(rs.getString("FRIST_EIT_SEGMENT"));
         approvalConditionBean.setOperation(rs.getString("OPERATION"));
         approvalConditionBean.setSecondKeyType(rs.getString("SECOND_KEY_TYPE"));
         approvalConditionBean.setSecondKeyValue(rs.getString("SECOND_KEY_VALUE"));
         approvalConditionBean.setSecondEitSegment(rs.getString("SECOND_EIT_SEGMENT"));
         approvalConditionBean.setApprovalCode(rs.getString("APPROVAL_CODE"));


         approvalConditionList.add(approvalConditionBean);

     }

 } catch (Exception e) {
     //("Error: ");
     e.printStackTrace();
 } finally {
     closeResources(connection, ps, rs);
 }
 return approvalConditionList;

}

这是我的 AppsproConnection Calss

     public static Connection getConnection(boolean commit) {
    if (CommonConfigReader.getValue("CONNECTION_TYPE").equalsIgnoreCase("JDBC")) {
        return getJDBCConnection(commit);
    } else {
        return getDSConnection(commit);
    }
}

public static Connection getConnection() {
    if (CommonConfigReader.getValue("CONNECTION_TYPE").equalsIgnoreCase("JDBC")) {
        return getJDBCConnection();
    } else {
        return getDSConnection();
    }
}

【问题讨论】:

  • 你没有从测试方法调用你想测试的方法。
  • 就像@Rashin 所说,在您的测试的第一行调用您的方法.getAllApprovalCondition(),然后再进行验证。
  • 它在这一行警告我 verify(mockConn, times(1)).prepareStatement(anyString()); WantedButNotInvoked:请问我应该怎么做? @arnonuem

标签: java unit-testing junit mocking mockito


【解决方案1】:

你没有从测试方法调用你想测试的方法。
您没有测试对象可以这样做。

class TestClass {
    private MyDao underTest;

    @Before
    public void setUp() throws SQLException {
        underTest = new MyDao();
        // mocking things...
    }
}

并且使用这个测试对象,你必须从一个测试方法中调用你真正想要测试的方法。

@Test
public void testCreateWithNoExceptions() throws SQLException {
    // ...

    ArrayList<ApprovalConditionBean> actualValues = underTest.getAllApprovalCondition();

    // assertions
}

如果您无法控制如何从静态类获取连接,那么您可以重构您的方法以从同一类中的另一个方法获取连接。

public ArrayList<ApprovalConditionBean> getAllApprovalCondition() {
    // ...
    connection = getConnection();
    // ...
}

Connection getConnection() {
    return AppsproConnection.getConnection();
}

如果您像这样使用,您可以以一种您可以管理为测试返回哪种连接的方式实例化测试对象。

@Before
public void setUp() throws SQLException {
    when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);
    doNothing().when(mockConn).commit();
    doNothing().when(mockPreparedStmnt).setString(anyInt(), anyString());
    when(mockPreparedStmnt.execute()).thenReturn(Boolean.TRUE);
    when(mockPreparedStmnt.getGeneratedKeys()).thenReturn(mockResultSet);
    when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);

    underTest = new MyDao(){
        @Override
        public Connection getConnection() {
            return mockConn;
        }
    };
}

我们正在返回来自getConnection 的模拟连接。从getAllApprovalCondition 方法调用此方法。在生产中,它仍然通过AppsproConnection 提供连接。

【讨论】:

  • 它在这一行警告我 verify(mockConn, times(1)).prepareStatement(anyString()); WantedButNotInvoked:我应该怎么做请@Rashin
  • 这个方法没有被调用,因为你要测试的方法没有被调用。
  • 我像你说的那样调用它,仍然是同样的警告。请问有什么建议吗? @Rashin
  • 您能告诉我们您的 dao 和 AppsproConnection 课程吗?正如我所见,您从AppsproConnection 获得了连接,但我看不到您是否将模拟的DataSource 注入到它。
  • 你在调用connection.prepareStatement(query);,但是在模拟when(mockConn.prepareStatement(anyString(), anyInt())).thenReturn(mockPreparedStmnt);试试when(mockConn.prepareStatement(anyString())).thenReturn(mockPreparedStmnt);第二个参数不需要。
猜你喜欢
  • 2015-04-07
  • 2014-01-18
  • 2018-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 2016-03-15
相关资源
最近更新 更多