首页 文章

Spring JUnit和Mockito - SimpleJdbcTemplate

提问于
浏览
2

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

    还有一件事 . 我通过用JdbcTemplate替换SimpleJdbcTemplate解决了这个问题 . 我是Java的新手,从.Net世界过来,最初只使用SimpleJdbcTemplate,因为我遇到了一些描述其用法的文档,完全满足了我的需求 . 但是Skaffman的评论让我更深入地研究了JdbcTemplate,然后我意识到我并不需要SimpleJdbcTemplate .
    尽管如此,问题的哲学部分仍然存在 . 你如何模拟只能通过询问容器本身来创建的东西?在我看来,Spring在这里违反了DI原则,通过严格依赖容器 .

  • 3

    允许您测试更多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());
    }
    }
    
  • 0

    你为什么要模仿JdbcTemplate?在内存数据库(如HSQL)中使用真实内容 .

  • 0

    你应该模拟一个接口(它有你需要的方法),而不是模仿具体的类 .

    例如 . :

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

相关问题