gpt4 book ai didi

java - 使用 Mockito 模拟结果集

转载 作者:行者123 更新时间:2023-11-30 01:57:06 26 4
gpt4 key购买 nike

如何模拟结果集?

在测试类中尝试模拟结果集,如下所示,但是,当尝试测试在语句中出现 UnnecessaryStubbingException 错误时:

voObj.setDept(rs.getString(2)); 

voObj.setDeptDesc(rs.getString(3));

关于如何模拟结果集有什么建议吗?

public class Example { 
public static void main(String[] s) {
method1();
method2();
..........
}

private Employee method1(String str) {
Connection conn = getConnection();
PreparedStatement pstmt = null;
.........
pstmt = conn.prepareStatement(strQuery.toString());
rs = pstmt.executeQuery();
int ilCounter = 0;
int maxId = method2(loc); //some DB calls here with select

if(null != rs) {
while(rs.next()) {
ilCounter++;
ObjVoBean voObj = new ObjVoBean();
voObj.setLoc(rs.getString(1));
voObj.setDept(rs.getString(2));
voObj.setDeptDesc(rs.getString(3));
}
.................
}
}

private Employee method2(String str1) {
Connection connOHM = getConnection();
PreparedStatement pstmt = null;
.........
//some DB call with select ...
}
}

public class ExampleTest {
@InjectMocks
Example example;

@Mock
private Connection c;

@Mock
private PreparedStatement preStmt;
.....

@Before
public void setUp() {
........
}

@Test
public void testMethod1() throws SQLException {
ResultSet resultSetMock = Mockito.mock(ResultSet.class);
when(resultSetMock.getString(1)).thenReturn("1111");
when(resultSetMock.getString(2)).thenReturn("2222");
when(resultSetMock.getString(3)).thenReturn("dept desc");

when(c.prepareStatement(any(String.class))).thenReturn(preStmt);
when(resultSetMock.next()).thenReturn(true).thenReturn(false);
doReturn(resultSetMock).when(preStmt).executeQuery();

example.method1("1111");
assertTrue(true);
}
}

最佳答案

为了能够模拟ResultSet,您应该模拟所有允许创建它的对象,即创建PreparedStatementConnection,它本身创建ResultSet。仅当您提供从客户端代码设置连接的方法时,模拟连接才会在测试代码中起作用。

这里 conn 是连接,应该首先作为测试装置中的依赖项注入(inject):

pstmt = conn.prepareStatement(strQuery.toString());

通常您会创建一个连接,例如:

conn = DriverManager.getConnection(DB_URL,USER,PASS);

或通过DataSource,例如:

conn = ds.getConnection();

因此,您应该将这部分抽象为接口(interface)或非最终类,并定义执行此处理的实现。通过这种方式你可以模拟创建Connection的部分。这样你就可以模拟整个链:Connection-PreparedStatement-ResultSet。

<小时/>

我个人会避免这种方式,因为 mock 太多的东西通常不是正确的选择。
在您的情况下,您需要模拟 ResultSet 以在加载 ResultSet 后测试后处理:

while(rs.next()) { 
ilCounter++;
ObjVoBean voObj = new ObjVoBean();
voObj.setLoc(rs.getString(1));
voObj.setDept(rs.getString(2));
voObj.setDeptDesc(rs.getString(3));
}

因此,作为替代方案,您可以将之前执行的所有代码移到处理持久性部分的特定类的方法中。这样你只需要模拟这个依赖和这个方法。您无需担心连接和任何 JDBC 细节。

EmployeeDAO employeeDAO; // dependency to mock

// constructor with dependency
public Example(EmployeeDAO employeeDAO){
this.employeeDAO = employeeDAO;
}

private Employee method1(String str) {
ResultSet resultSet = employeeDAO.load(str);

if(null != rs) {
while(rs.next()) {
ilCounter++;
ObjVoBean voObj = new ObjVoBean();
voObj.setLoc(rs.getString(1));
voObj.setDept(rs.getString(2));
voObj.setDeptDesc(rs.getString(3));
}
.................
}
}

当然,DAO 组件也必须经过统一测试。
正如前面所说,断言连接已创建或返回PreparedStatement 不会带来任何值(value)。虽然测试您的查询是否执行您期望的结果在功能覆盖范围方面更有趣。
在这种情况下,您希望针对内存数据库(例如 H2)对其进行测试,因为单元测试不是集成测试,并且单元测试必须快速执行。
要编写 DAO/存储库测试,DbunitDbSetup是很好的候选者,因为它们提供了在每次测试之前设置数据库的工具(主要是注入(inject)数据和清除数据)。

关于java - 使用 Mockito 模拟结果集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54042608/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com