Spring JUnit и Mockito - SimpleJdbcTemplate - PullRequest
       75

Spring JUnit и Mockito - SimpleJdbcTemplate

2 голосов
/ 11 февраля 2011

Учитывая класс, который расширяет 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 - mocking JdcbTemplate не влияет на SimpleJdbcTemplate. Итак, как это сделать, когда для него нет открытых сеттеров, и единственный способ заставить SimpleJdbcTemplate доверять этому - это использовать метод getSimpleJdbcObject ()?

Ответы [ 4 ]

3 голосов
/ 15 февраля 2011

Вместо того, чтобы издеваться над конкретным классом, вы должны издеваться над интерфейсом (в котором есть нужные вам методы).

например:.

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();
    }
}
0 голосов
/ 08 января 2015

Другой способ, позволяющий вам протестировать большее количество данных, - это смоделировать соединение, подготовленное заявление и набор результатов. Это немного больше работы, чем просто издеваться над 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 голосов
/ 13 февраля 2011

И еще одна вещь. Я решил эту проблему, заменив SimpleJdbcTemplate на JdbcTemplate . Я немного новичок в Java, перешел из мира .Net и изначально использовал SimpleJdbcTemplate только потому, что натолкнулся на некоторую документацию, описывающую его использование, которая полностью отвечала моим потребностям. Но комментарии Скаффмана привели меня к более глубокому расследованию JdbcTemplate , и тогда я понял, что мне действительно не нужно SimpleJdbcTemplate .
Тем не менее, философская часть вопроса остается в силе. Как вы издеваетесь над чем-то, что может быть создано только путем запроса самого контейнера? Мне кажется, что Spring нарушает принцип DI, делая жесткую зависимость от контейнера.

0 голосов
/ 12 февраля 2011

Зачем вы издеваетесь над JdbcTemplate?Используйте реальную вещь с базой данных в памяти, такой как HSQL.

...