Spring JUnit和Mockito - SimpleJdbcTemplate

时间:2011-02-11 20:07:20

标签: java spring mockito jdbctemplate

给定一个扩展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()?

4 个答案:

答案 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());
}
}