How can I mock a call to JdbcTemplate.query(String, Object[], int[] RowMapper<T>) in my JUnit tests? (specifically the arrays)

huangapple go评论81阅读模式
英文:

How can I mock a call to JdbcTemplate.query(String, Object[], int[] RowMapper<T>) in my JUnit tests? (specifically the arrays)

问题

我想模拟JdbcTemplate中的这个方法:

public <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper) throws DataAccessException {
    return result(query(sql, args, argTypes, new RowMapperResultSetExtractor<>(rowMapper)));
}

我正在使用JUnit 5和Hamcrest。

我尝试了很多方法,我觉得应该有效的方法是:

when(db.query(anyString(), any(Object[].class), any(int[].class), new IdRowMapperImpl())).thenReturn(profileIds);

但是它不起作用。我在这里做错了什么?

我如何模拟这些数组?

英文:

I want to mock this method in JdbcTemplate:

	public &lt;T&gt; List&lt;T&gt; query(String sql, Object[] args, int[] argTypes, RowMapper&lt;T&gt; rowMapper) throws DataAccessException {
		return result(query(sql, args, argTypes, new RowMapperResultSetExtractor&lt;&gt;(rowMapper)));
	}

I'm using JUnit 5 and Hamcrest.

I've tried numerous things, the one I feel should have worked is this:

when(db.query(anyString(), any(Object[].class), any(int[].class), new IdRowMapperImpl())).thenReturn(profileIds);

but it doesn't. What am I doing wrong here?
How can I mock the arrays?

答案1

得分: 1

如果您使用参数匹配,那么所有参数都应该是相同的类型。在您的情况下,如下所示:

when(jdbcTemplate.query(
                anyString(),
                any(Object[].class),
                any(int[].class),
                any(RowMapper.class)
        )).thenReturn(profileIds);
英文:

If you use argument matches then all parameters should be the same type. In your case like:

when(jdbcTemplate.query(
                anyString(),
                any(Object[].class),
                any(int[].class),
                any(RowMapper.class)
        )).thenReturn(profileIds);

答案2

得分: 1

Here is the translated code snippet:

你认为应该工作的模拟在这里不会起作用因为你同时使用了参数匹配器和显式值如果你想在匹配器和显式值一起使用你需要使用`eq`匹配器告诉 Mockito

```java
when(db.query(anyString(), any(Object[].class), any(int[].class), eq(new IdRowMapperImpl()))).thenReturn(profileIds);

然而,这也不会起作用,因为new IdRowMapperImpl()将是一个不同于实际查询中传递的对象。

最后,在when模拟期间声明特定类型通常会适得其反。除非你想根据传递的值明确返回不同的对象,否则when(db.query(any(), any(), any(), any())).thenReturn(profileIds);同样有用。然后,你可以使用verify来断言是否调用了预期的方法,并且实际传递给它的值是否符合预期。

也许可以这样做:

@Test
public void testRetrieveData()
{
  String expectedQuery = "这是我的查询";
  ArgumentCaptor<Object> objectCaptor = ArgumentCaptor.forClass(Object.class);
  ArgumentCaptor<RowMapper> mapperCaptor = ArgumentCaptor.forClass(RowMapper.class);
  when(db.query(any(), any(), any(), any())).thenReturn(profileIds);
 
  MyDao.getMyData();

  verify(db, times(1)).query(eq(expectedQuery), (Object[]) objectCaptor .capture(), any(int[].class), mapperCaptor.capture());
  assertEquals(expectedObjectArray, objectCaptor.getValue());
  assertTrue(mapperCaptor.getValue() instanceof IdRowMapperImpl);
}
英文:

The mock that you thought should work won't work because you are using argument matchers and explicit values at the same time. If you want to use an explicit value along with matchers, you need to let mockito know that with the eq matcher.

when(db.query(anyString(), any(Object[].class), any(int[].class), eq(new IdRowMapperImpl()))).thenReturn(profileIds);

However, this also will not work because the new IdRowMapperImpl() will be a different object than the one passed to passed in the actual query.

Finally, declaring specific types during a when mock can often be counterproductive. Unless you want to specifically return a different object depending on the values passed, then when(db.query(any(), any(), any(), any())).thenReturn(profileIds); can be just as useful. You can then use verify to assert that the expected method was called, and that the expected values were actually passed to it.

Maybe something like this:

@Test
public void testRetrieveData()
{
  String expectedQuery = &quot;THIS IS MY QUERY&quot;;
  ArgumentCaptor&lt;Object&gt; objectCaptor = ArgumentCaptor.forClass(Object.class);
  ArgumentCaptor&lt;RowMapper&gt; mapperCaptor = ArgumentCaptor.forClass(RowMapper.class);
  when(db.query(any(), any(), any(), any())).thenReturn(profileIds);
 
  MyDao.getMyData();

  verify(db, times(1)).query(eq(expectedQuery), (Object[]) objectCaptor .capture(), any(int[].class), mapperCaptor.capture());
  assertEquals(expectedObjectArray, objectCaptor.getValue());
  assertTrue(mapperCaptor.getValue() instanceof IdRowMapperImpl);
}

</details>



huangapple
  • 本文由 发表于 2023年5月11日 18:17:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76226540.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定