2015-08-14 122 views
1

我想使用Mockito(和PowerMockito,如果需要)測試我的DAO方法,但我不知道如何執行此操作。調用靜態方法的最大問題(MySQLStationDAO中的MySQLDAOFactory.getConnection())。你可以幫我嗎?使用Mockito和PowerMockito進行DAO測試

我取得聯繫是這樣的:

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

究竟是什麼問題?你有例外嗎? – BetaRide

+0

我們可能還需要一些額外的信息。你的DataSource在哪裏配置? – Nitax

回答

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的原因,建議要麼存根或驗證調用,而不是兩個。

在一般情況下,你可能想諮詢Mockito docsPowerMockito docs以獲取更多信息。

這是使用JUnit 4.11創建

完整的示例,1.9.5的Mockito和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數據集驗證返回的結果。

0

正如你所說,你的問題是,當你調用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類。

+0

請注意''getConnection()'方法是靜態的。你的答案只適用於實例方法。 – Constantine

+0

哦,是的。我沒有看到。然後Mockito是不夠的,因爲你不能嘲笑靜態方法。在這種情況下,同意給予asnwer – iseji