给定一个扩展SimpleJdbcDaoSupport的类,你如何模拟SimpleJdbcTemplate?
public class SimpleJdbcDaoSupportExtension extends SimpleJdbcDaoSupport {
public SimpleJdbcDaoSupportExtension (JdbcTemplate jdbcTemplate){
super.setJdbcTemplate(jdbcTemplate);
}
public MyDomainObj getResult(){
SimpleJdbcTemplate sjdbc = getSimpleJdbcTemplate();
MyDomainObj result = sjdbc.query(*whatever necessary args*.);
return result;
}
}
然后,使用Mockito:
public class Test {
@Mock private JdbcTemplate mockedJdbcTemplateDedendency;
private SimpleJdbcDaoSupportExtension testObj;
@Before
public void doBeforeEachTestCase() {
MockitoAnnotations.initMocks(this);
SimpleJdbcDaoSupportExtension sje = new SimpleJdbcDaoSupportExtension (mockedJdbcTemplateDedendency);
}
@Test
public final void test(){
when(mockedJdbcTemplateDedendency.query("what to query").thenReturn(new MyDomainObj());
}
}
注入了模拟的JdbcTemplate,但由于dao类依赖于SimpleJdbcTemplate来进行查询(用于映射到对象),并且它是由SimpleJdbcDaoSupport在内部构造的 - 模拟JdcbTemplate对SimpleJdbcTemplate没有影响。那么如何做到这一点,当没有公共设置器时,修改SimpleJdbcTemplate的唯一方法就是依赖于那个方法getSimpleJdbcObject()?
答案 0 :(得分:3)
不应该嘲笑具体类,而应该模拟一个接口(它有你需要的方法)。
e.g:
public class SimpleJdbcDaoSupportExtension extends SimpleJdbcDaoSupport implements MyDomainDao{
public SimpleJdbcDaoSupportExtension (JdbcTemplate jdbcTemplate){
super.setJdbcTemplate(jdbcTemplate);
}
public MyDomainObj getResult(){
SimpleJdbcTemplate sjdbc = getSimpleJdbcTemplate();
MyDomainObj result = sjdbc.query(*whatever necessary args*.);
return result;
}
}
public class Test {
@Mock private MyDomainDao myDomainDao ;
private YourController yourController;
@Before
public void doBeforeEachTestCase() {
MockitoAnnotations.initMocks(this);
yourController = new YourController(myDomainDao);
}
@Test
public final void testSomething(){
when(myDomainDao.getResult().thenReturn(new MyDomainObj());
//on to testing the usages of myDomainDao
yourController.doSomething();
//verify
verify(myDomainDao, times(2)).getResult();
}
}
答案 1 :(得分:0)
你为什么要模仿JdbcTemplate?将内容数据库与HSQL一起使用。
答案 2 :(得分:0)
还有一件事。我通过将 SimpleJdbcTemplate 替换为 JdbcTemplate 解决了这个问题。我是Java的新手,从.Net世界过来,最初只使用 SimpleJdbcTemplate ,因为我遇到了一些描述其用法的文档,完全满足了我的需求。但是Skaffman的评论让我更深入地研究了 JdbcTemplate ,然后我意识到我并不需要 SimpleJdbcTemplate 。 尽管如此,问题的哲学部分仍然存在。你如何模仿只能通过询问容器本身来创建的东西?在我看来,Spring在这里违反了DI原则,通过严格依赖容器。
答案 3 :(得分:0)
允许您测试更多dao的另一种方法是模拟连接,preparedstatement和resultset。这比仅仅模拟jdbctemplate要多一些,但是可以让你验证预备语句是否设置了正确的值,以及你的自定义行映射器是否正常工作。
public class Test {
private MyDao dao;
private JdbcTemplate jdbcTemplate;
private Connection conn;
private PreparedStatement ps;
private ResultSet rs;
@Before
public void setUp() throws Exception {
dao = new MyDao();
conn = mock(Connection.class);
ps = mock(PreparedStatement.class);
rs = mock(ResultSet.class);
jdbcTemplate = new JdbcTemplate(new SingleConnectionDataSource(conn, false));
doa.setJdbcTemplate(jdbcTemplate);
}
@Test
public void test() throws Exception {
when(conn.prepareStatement(any(String.class))).thenReturn(ps);
when(ps.executeQuery()).thenReturn(rs);
// return one row
when(rs.next()).thenReturn(true).thenReturn(false);
when(rs.getInt("id")).thenReturn(1234);
when(rs.getString("name")).thenReturn("Bob");
MyDto myDto = dao.someDaoMethod(...)
// verify ParameterSource
verify(ps, times(1)).setInt(1, 1234);
// these verify if you are mapping the columns to the right object attribute.
assertEquals(1234, myDto.getId().intValue());
assertEquals("Bob", myDto.getName());
}
}