[英]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類。
JUnit:在類級別使用@RunWith(PowerMockRunner.class)
。
TestNG:使您的測試類擴展PowerMockTestCase
。
在類級別使用@PrepareForTest(MySQLDAOFactory.class)
,以指示PowerMock准備要測試的MySQLDAOFactory
類。
使用PowerMockito.mockStatic(MySQLDAOFactory.class)
來模擬MySQLDAOFactory
類的所有方法。
也可以使用部分嘲諷 :
PowerMockito.stub(PowerMockito.method(MySQLDAOFactory.class, "getConnection")).toReturn(Mockito.mock(Connection.class));
使用類似的東西來對getConnection()
進行存根:
Connection mockConnection = Mockito.mock(Connection.class); Mockito.when(MySQLDAOFactory.getConnection()).thenReturn(mockConnection);
執行getAllStations()
上的一個真實的例子 MySQLStationDAO
,因為你正在測試MySQLStationDAO
類。
如果要驗證是否已調用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.