命名参数JdbcTemplate中的GeneratedKeyHolder单元测试

8

我正在尝试为一个包含以下代码的函数编写单元测试:

    KeyHolder newCode = new GeneratedKeyHolder();
    try {
        namedParameterJdbcTemplate.update(sql, paramMap, newCode);
    } catch (DuplicateKeyException e) {
        logger.error("Duplicate Key");
    }
    data.setId(newCode.getKey().intValue());

现在,使用Mockito:

Mockito.when(namedParameterJdbcTemplate.update(Mockito.anyString(), Mockito.any(MapSqlParameterSource.class), Mockito.any(GeneratedKeyHolder.class))).thenReturn(1);

那么我该如何使用GeneratedKeyHolder来填充数据呢?谢谢。
2个回答

13

我将以以下方式之一进行操作:

  1. 注入密钥。
  2. 桩方法调用并在那里设置密钥。

方法1:当我说“注入密钥”时,实际上是指注入一个KeyFactory。这意味着您可以在测试中控制结果。例如:

KeyHolder newCode = injectedKeyFactory.getKeyHolder();
try {
    namedParameterJdbcTemplate.update(sql, paramMap, newCode);
} catch (DuplicateKeyException e) {
    logger.error("Duplicate Key");
}
data.setId(newCode.getKey().intValue());

然后在测试中:

KeyHolder newCode = mock(KeyHolder.class);
Mockito.when(namedParameterJdbcTemplate.update(Mockito.anyString(), Mockito.any(MapSqlParameterSource.class), newCode)).thenReturn(1);
Mockito.when(newCode.getKey()).thenReturn(__preferredId__);

密钥工厂是一个简单的工厂,它只返回一个新的GeneratedKeyHolder。它在构建时被注入,因此这个方法假定您正在使用DI。

方法2

Mockito.when(namedParameterJdbcTemplate.update(Mockito.anyString(), Mockito.any(MapSqlParameterSource.class), Mockito.any(GeneratedKeyHolder.class))).thenAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        Map<String, Object> keyMap = new HashMap<String, Object>();
        keyMap.put("", __preferredId__);
        ((GeneratedKeyHolder)args[2]).getKeyList().add(keyMap);
    }
}).andReturn(1);

我并没有真正使用过Mockito,所以如果代码不太正确请见谅。:)


2
很好的回答!我使用了第二种方法。唯一缺少的是一个返回语句。如果你想要完全返回我想要的东西,它应该在最后声明"return 1"。 - Gleeb

0

这对我起作用了。它与上面的答案略有不同。

被测试的类
将 KeyHolder 工厂声明为类属性并在构造函数中注入:

private final NamedParameterJdbcTemplate jdbcTemplate;
private final GeneratedKeyHolderFactory keyHolderFactory;

public AccountJdbcAdapter(NamedParameterJdbcTemplate jdbcTemplate, GeneratedKeyHolderFactory keyHolderFactory) {
     this.keyHolderFactory = keyHolderFactory;
        this.jdbcTemplate = jdbcTemplate;
}

    private Long executeCreateAccount(Account newAccount){
        KeyHolder keyHolder = keyHolderFactory.newKeyHolder();
        jdbcTemplate.update(
            queryCreateAccount,
            createAccountParams(newAccount),
            keyHolder
        );

      YOU WILL INJECT MOCKED VALUE HERE --> 
      Long accountId = keyHolder.getKey().longValue();

      }

声明工厂类

   @Component
    public class GeneratedKeyHolderFactory {
        public GeneratedKeyHolderFactory(){

        }
        public KeyHolder newKeyHolder() {
            return new GeneratedKeyHolder();
        }
    }

测试: 模拟工厂,获取一个新的KeyHolder实例并填充值

private final GeneratedKeyHolderFactory factory = mock(GeneratedKeyHolderFactory.class);
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate = mock(NamedParameterJdbcTemplate.class);
private final AccountJdbcAdapter accountJdbcAdapter = new AccountJdbcAdapter(namedParameterJdbcTemplate, factory);


  void createAccountsOk() {
        KeyHolder keyHolder = new GeneratedKeyHolder(Arrays.asList(Map.of("accountId", accountId)));
        when(factory.newKeyHolder()).thenReturn(keyHolder);

        when(namedParameterJdbcTemplate.update(any(), any(MapSqlParameterSource.class), any(GeneratedKeyHolder.class))).thenReturn(1);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接