我正在尝试将单元测试写入包含以下代码的函数:
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
?
感谢。
答案 0 :(得分:7)
我会通过以下方式之一来做到这一点:
方法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);