我想使用Spring和JDBC实现一个数据库阅读器。
@Component
public class MyReader() {
public void read() {
/* Other code */
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
String myDbValue = rs.getString("myColumn");
}
/* Other code */
}
}
如果列myColumn
不存在,我想测试我的类的行为。
一个解决方案是将常数myColumn
移动到私有方法,但是有些人告诉其他用户,嘲笑私有方法有味道,看看Raedwalds的评论,我同意。我也可以模拟数据库文件本身,但是模拟文件也不是一个好方法。
有什么办法处理这个问题吗?
您的测试代码,因此您选择模拟什么/如何模拟,本质上和您正在测试的方法的功能密不可分。现在,这并不意味着它应该绑定到该方法的实现(您希望保持相当的解耦),但是该方法的核心目的是您应该测试什么。这就是为什么精心设计、深思熟虑的测试可以驱动良好的API设计。
因此,您需要问自己的问题是 read
方法在做什么?.
我怀疑执行查询返回的Statement
和ResultSet
都是实现细节,您可以为测试的目的模拟出来。
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.mockito.Matchers.*;
import java.sql.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MyReaderTest {
@InjectMocks
private MyReader myReader;
@SuppressWarnings("unchecked")
@Before
public void setUp() throws Exception {
Statement s = mock(Statement.class);
ResultSet rs = mock(ResultSet.class);
when(s.executeQuery(anyString())).thenReturn(rs);
when(rs.getString("myColumn")).thenThrow(SQLException.class);
}
@Test
public void testRead_AccessNonExistentColumn() {
// Use mock statement and mock resultset
}
}