使用Mockito和PowerMockito进行DAO测试

时间:2015-08-14 15:11:48

标签: java mockito dao powermockito

我想使用Mockito(以及PowerMockito,如果需要)测试我的DAO方法,但我不知道如何做到这一点。调用静态方法(MySQLStationDAO中的MySQLDAOFactory.getConnection())的最大问题。你能帮助我吗?

我以这种方式获得连接:

public class MySQLDAOFactory extends DAOFactory {     
        public static Connection getConnection() throws DAOException {
            Connection con = null;
            try {
                con = getDataSource().getConnection();
            } catch (SQLException e) {
                throw new DAOException(Messages.CANNOT_OBTAIN_CONNECTION, e);
            }
            return con;
        }

这是一个DAO方法:

public class MySQLStationDAO implements StationDAO {
    @Override
    public List<Station> getAllStations() throws DAOException {
        List<Station> stations = new ArrayList<>();
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            con = MySQLDAOFactory.getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery(MySQLQueries.SQL_GET_ALL_STATIONS);
            while (rs.next()) {
                stations.add(extractStation(rs));
            }
        } catch (SQLException e) {
            throw new DAOException(Messages.CANNOT_OBTAIN_ALL_STATIONS, e);
        } finally {
            MySQLDAOFactory.close(con, stmt, rs);
        }
        return stations;
    }

1 个答案:

答案 0 :(得分:0)

  1. JUnit:在班级使用@RunWith(PowerMockRunner.class)

    TestNG:让您的测试类扩展PowerMockTestCase

  2. 在课程级别使用@PrepareForTest(MySQLDAOFactory.class),以指示PowerMock准备MySQLDAOFactory课程进行测试。

  3. 请使用PowerMockito.mockStatic(MySQLDAOFactory.class) 模拟MySQLDAOFactory类的所有方法。

    也可以使用partial mocking

    PowerMockito.stub(PowerMockito.method(MySQLDAOFactory.class, "getConnection")).toReturn(Mockito.mock(Connection.class));

  4. 使用类似的东西来存根getConnection()

    Connection mockConnection = Mockito.mock(Connection.class); Mockito.when(MySQLDAOFactory.getConnection()).thenReturn(mockConnection);

  5. getAllStations()实例上执行MySQLStationDAO,因为您正在测试MySQLStationDAO类。

  6. 如果您想验证是否已调用getConnection()方法,请使用类似的内容:

    PowerMockito.verifyStatic(); MySQLDAOFactory.getConnection();

    但是,请阅读Mockito.verify(T) javadoc,了解建议存根或验证调用的原因,而不是两者。

  7. 一般情况下,您可以咨询Mockito docsPowerMockito docs以获取更多信息。

    使用JUnit 4.11,Mockito 1.9.5和PowerMock(PowerMockito)1.5.6创建的完整示例(请注意版本,因为存在许多兼容性问题):

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(MySQLDAOFactory.class)
    public class MySQLDAOFactoryTest {
    
        private StationDAO stationDAO;
    
        @Mock
        private Connection mockConnection;
    
        @Mock
        private Statement mockStatement;
    
        @Mock
        private ResultSet mockResultSet;
    
        @Before
        public void setUp() {
            stationDAO = new MySQLStationDAO();
        }
    
        @Test
        public void testGetAllStations_StatementCreated() throws DAOException, SQLException {
            // given
            PowerMockito.mockStatic(MySQLDAOFactory.class);
            Mockito.when(MySQLDAOFactory.getConnection()).thenReturn(mockConnection);
            Mockito.when(mockConnection.createStatement()).thenReturn(mockStatement);
            Mockito.when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet);
    
            // when
            stationDAO.getAllStations();
    
            // then
            Mockito.verify(mockConnection).createStatement();
        }
    }
    

    下一步是什么?检查是否已使用预期参数调用executeQuery()方法?测试SQLException的处理方式?这些是单元测试的合理方案,但是集成测试呢?为此,我建议DBUnit。它将测试数据库置于测试运行之间的已知状态,并允许根据预期的XML数据集验证返回的结果。