我有一个静态类,它有这个方法:
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
希望能帮助到你!