2015-08-14 98 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