在namedParameterJdbcTemplate中对GeneratedKeyHolder进行单元测试

时间:2014-04-07 10:10:48

标签: java spring unit-testing mockito

我正在尝试将单元测试写入包含以下代码的函数:

    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 个答案:

答案 0 :(得分:7)

我会通过以下方式之一来做到这一点:

  1. 注入钥匙。
  2. 存根方法调用并在那里设置密钥。
  3. 方法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,很抱歉,如果代码不太正确的话。 :)

答案 1 :(得分: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);
相关问题