java – 使用mockito模拟结果集

我有一个静态类,它有这个方法:

    public static Connection getDbConnection(String tenant, String product) {
    Connection connection = null;

    try {
        Map<String,Map<String,String >> databaseConnectionTable = PropertyUtil.getInstance().getDatabaseConnectionTable();
        Map<String,String> properties = getHighestPrecedenceMap(databaseConnectionTable,tenant,product);

        if (properties!=null) {

            Class.forName(properties.get("db.driver"));
            connection = DriverManager.getConnection(
                properties.get("db.url"),
                properties.get("db.user"),
                properties.get("db.password"));
        }
    } catch (ClassNotFoundException e) {
            LOGGER.error("Message",e);
        } catch (SQLException e) {
            LOGGER.error("Message:",e);
        }
    return connection;

}

然后我有另一个类,它有一个方法来获取给定SQL查询字符串的结果集,这个方法调用上面的方法,下面是源代码:

   public static ResultSet getResultSetFromSql(String sql,String tenant,String product) {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet rs = null;
    try {
        if(product!=null)
        connection = SqlConnectionUtil.getDbConnection(tenant,product);
        RccSqlParameterMap parameterMap = RccSqlParameterMap.getParameterMap();

        if(connection!=null) {
            if (parameterMap.getSqlParameters().entrySet().size() > 0)
                sql = parameterMap.SqlMessageFormat(sql);
            else
                LOGGER.error("Parameter map isn't set please initialize it");

            LOGGER.info("Executing SQL: " + sql);
            statement = connection.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY);
            if (!statement.execute()) {
                LOGGER.error("No results found for statement!");
                return null;
            }
            rs = statement.getResultSet();
        }else{
            LOGGER.error("Coudn't create Connection Object");
        }
    } catch (SQLException e) {
        LOGGER.error("Message", e);
    }
    return rs;
}

我需要编写用于测试这些的单元测试,以便在内存中实现我能够通过从文件中读取行来模拟结果集,所以当我实例化结果集mocker并执行getResultSet()时,我得到结果集对象,我面临的问题是将这个mocker与上面的方法集成在一起.请建议一种方法来做到这一点.

解决方法:

使用当前的实现,不可能模拟连接对象,因为Mockito无法模拟静态调用,这可以通过PowerMockito实现.有可能的解决方案(随意改变测试逻辑,它只是一个工作的骨架与你的模拟)

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import java.util.Map;
import java.util.HashMap;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ SqlConnectionUtil.class, RccSqlParameterMap.class })
public class TestQueryRunner {

    @Test
    public void testGetResultSetFromSql() throws SQLException {
        ResultSet rs = mock(ResultSet.class);
        when(rs.getString(eq("foo"))).thenReturn("This is mocked value");

        PreparedStatement stmt = mock(PreparedStatement.class);
        when(stmt.getResultSet()).thenReturn(rs);
        when(stmt.execute()).thenReturn(true);

        Connection connection = mock(Connection.class);
        when(connection.prepareStatement(anyString(), anyInt(), anyInt()))
                .thenReturn(stmt);

        PowerMockito.mockStatic(SqlConnectionUtil.class);
        PowerMockito.when(SqlConnectionUtil.getDbConnection(anyString(), anyString()))
                .thenReturn(connection);

        Map<String, String> sqlParams = new HashMap<>();
        sqlParams.put("param1", "value1");
        RccSqlParameterMap paramMap = mock(RccSqlParameterMap.class);
        when(paramMap.getSqlParameters()).thenReturn(sqlParams);

        PowerMockito.mockStatic(RccSqlParameterMap.class);
        PowerMockito.when(RccSqlParameterMap.getParameterMap()).thenReturn(paramMap);       

        ResultSet actual = QueryRunner.getResultSetFromSql("SELECT ...",
                "tenant", "product");
        assertEquals(rs, actual);
        assertEquals("This is mocked value", actual.getString("foo"));
    }

}

另外,一些一般建议:

>在每个if-else语句中始终使用{},即使它们是单行的.这将在以后合并和支持您的代码更方便.
>重写代码以正确管理数据库连接.他们应该关闭!使用一些第三方连接池机制,如Apache DBCP

希望能帮助到你!

上一篇:java – 如何使用Mockito测试要测试的类中的throws子句


下一篇:java 集合(Set1)