簡體   English   中英

使用Mockito和PowerMockito進行DAO測試

[英]Using Mockito and PowerMockito for DAO testing

我想使用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;
    }

如您所說,您的問題是當您調用MySQLDAOFactory.getConnection();時。 在測試方面,您想測試MySQLStationDAO類。 這是您的SUT(被測系統)。 這意味着您必須模擬SUT具有的所有依賴關系。 在這種情況下,為MySQLDAOFactory。

為此,您可以使用Mockito輕松模擬該類並對MySQLDAOFactory呈現的方法進行存根。 一個例子是

    package com.iseji.app.dao;

import junit.framework.Assert;
import org.junit.Before;    
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

import java.sql.Connection;

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class TestMySqlDaoFactory {

    MySqlDaoFactory mySqlDaoFactory;
    Connection connection;

    @Before
    public void setUp() throws DAOException {
        mySqlDaoFactory = mock(MySqlDaoFactory.class);
        connection = mock(Connection.class);
    }

    @Test(expected = DAOException.class)
    public void testEmptyUrlGetsDaoException() throws DAOException {
        when(mySqlDaoFactory.getConnection(null)).thenThrow(new DAOException());
        mySqlDaoFactory.getConnection(null);
    }

    @Test
    public void testFullUrlGetsConnection() throws DAOException {
        when(mySqlDaoFactory.getConnection(anyString())).thenReturn(connection);
        Assert.assertEquals(mySqlDaoFactory.getConnection(anyString()), connection);
    }
}

如您所見,您可以指定DaoFactory的行為。 這樣可以隔離您要測試的Dao類。

  1. JUnit:在類級別使用@RunWith(PowerMockRunner.class)

    TestNG:使您的測試類擴展PowerMockTestCase

  2. 在類級別使用@PrepareForTest(MySQLDAOFactory.class) ,以指示PowerMock准備要測試的MySQLDAOFactory類。

  3. 使用PowerMockito.mockStatic(MySQLDAOFactory.class)來模擬MySQLDAOFactory類的所有方法。

    也可以使用部分嘲諷

    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,以了解為什么建議對它進行存根或驗證調用,而不是兩者都進行。

通常,您可能需要查閱Mockito文檔PowerMockito文檔以獲取更多信息。

使用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數據集驗證返回的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM