java - 使用 Mockito 和 PowerMockito 进行 DAO 测试

标签 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. 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. 使用类似的东西来 stub getConnection():

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

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

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

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

    但是,请阅读Mockito.verify(T) javadoc 解释了为什么建议 stub 或验证调用,而不是两者都进行。

一般情况下,您可能需要咨询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 数据集验证返回的结果。

关于java - 使用 Mockito 和 PowerMockito 进行 DAO 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32013280/

相关文章:

Java 应用程序不知道正在打开的文件的名称 - Mac OS X

java - DI 的部分模拟?

mockito - 部分 mock 被认为是不好的做法? (莫基托)

android - 实时数据返回旧值,onChanged 触发多次

java - DAO 应该扩展数据对象吗?

java - 在标签中看不到滚动 Pane - Swing

java - 将 StreamingOutput 转换为字符串

java - 当我的代码失败时,如何使用 java 生成电子邮件警报

java - 如何使用 SpEL 处理 Thymeleaf 中的本地化消息

java - 当我组合构造函数注入(inject)(子类)和属性注入(inject)(父类)时,@InjectMocks 给我 null