Mockito 使用正则表达式验证是否使用正确的参数调用了方法
Mockito verify that method is called with correct argument using regex
描述
我正在尝试测试以下 class:
Class UserSynchronizer(){
private static org.apache.log4j.Logger log = ... ;
public Sync(candidate) {
...
if (candidate.inValidForSync()) {
log.debug("Candidate #" + candidate.getId() + ": Not syncing");
}
else {
log.debug("Syncing");
}
}
}
我想看看 mockito 是否可以检测调用 log.debug
时使用的参数,然后我想看看我是否可以对其进行某种正则表达式检查。换句话说,我想:
- 捕获提供给日志对象的参数(我在我的测试 atm 中模拟)
- 检查(使用正则表达式)它是否与像 "Candidate #\d+: Not syncing" 这样的模式匹配,因为我的模拟候选对象返回 false
测试代码
下面的代码是我的起点:
public void verifySyncDoesntSyncWhenInvalid(){
//Setup candidate mock
Candidate invalidSyncCandidateMock = mock(Candidate.class);
when(invalidSyncCandidateMock.inValidForSync()).thenReturn(true);
//Setup log mock
UserSynchronizer userSynchronizer = ...;
Field logField = userSynchronizer.getClass().getDeclaredField("log");
logField.setAccessible(true);
logField.set(userSynchronizer, logMock);
//Call sync
userSynchronizer.sync(invalidSyncCandidateMock);
//Verify that debug was called with ("Candidate #\d+: Not syncing")
???
}
问题
问题是 log.debug
被调用了多次。我想捕获提供给 log.debug
的参数,并确保当它与对同步无效的候选人一起调用时,记录器对象会正确记录候选人未同步。
编辑:如果之前有人问过这个问题,我深表歉意。恳请您 post 回答相关问题 link :)
你可以使用这个:
final List<String> messages = new ArrayList<>();
final Answer<Void> catchMeAll = new Answer<Void>()
{
@Override
public Void answer(final InvocationOnMock invocation)
{
messages.add((String) invocation.getArguments()[0]);
}
}
doAnswer(catchMeAll).when(logMock).debug(anyString());
(注意:此代码假定 Logger
的 .debug()
方法 returns void
;我不知道任何 Logger
没有,但谁知道)
另一种匹配方法是使用支持正则表达式的 Hamcrest 匹配器:
verify(logMock).debug(argThat(matchesPattern("Candidate #\d+: Not syncing")));
请注意,您必须自己编写,或使用尚未包含的 PatternMatcher or hamcrest-text-patterns
as in JavaHamcrest issue #2。
Mockito 在标准 org.mockito.Matchers class 中提供正则表达式匹配器。下面是一个示例,说明如何使用此函数来验证具有正确参数值的调用:
verify(restMock, times(1)).exchange(matches(".*text=welcome.*to.*blah"), eq(HttpMethod.GET), any(ResponseEntity.class), eq(String.class));
描述
我正在尝试测试以下 class:
Class UserSynchronizer(){
private static org.apache.log4j.Logger log = ... ;
public Sync(candidate) {
...
if (candidate.inValidForSync()) {
log.debug("Candidate #" + candidate.getId() + ": Not syncing");
}
else {
log.debug("Syncing");
}
}
}
我想看看 mockito 是否可以检测调用 log.debug
时使用的参数,然后我想看看我是否可以对其进行某种正则表达式检查。换句话说,我想:
- 捕获提供给日志对象的参数(我在我的测试 atm 中模拟)
- 检查(使用正则表达式)它是否与像 "Candidate #\d+: Not syncing" 这样的模式匹配,因为我的模拟候选对象返回 false
测试代码
下面的代码是我的起点:
public void verifySyncDoesntSyncWhenInvalid(){
//Setup candidate mock
Candidate invalidSyncCandidateMock = mock(Candidate.class);
when(invalidSyncCandidateMock.inValidForSync()).thenReturn(true);
//Setup log mock
UserSynchronizer userSynchronizer = ...;
Field logField = userSynchronizer.getClass().getDeclaredField("log");
logField.setAccessible(true);
logField.set(userSynchronizer, logMock);
//Call sync
userSynchronizer.sync(invalidSyncCandidateMock);
//Verify that debug was called with ("Candidate #\d+: Not syncing")
???
}
问题
问题是 log.debug
被调用了多次。我想捕获提供给 log.debug
的参数,并确保当它与对同步无效的候选人一起调用时,记录器对象会正确记录候选人未同步。
编辑:如果之前有人问过这个问题,我深表歉意。恳请您 post 回答相关问题 link :)
你可以使用这个:
final List<String> messages = new ArrayList<>();
final Answer<Void> catchMeAll = new Answer<Void>()
{
@Override
public Void answer(final InvocationOnMock invocation)
{
messages.add((String) invocation.getArguments()[0]);
}
}
doAnswer(catchMeAll).when(logMock).debug(anyString());
(注意:此代码假定 Logger
的 .debug()
方法 returns void
;我不知道任何 Logger
没有,但谁知道)
另一种匹配方法是使用支持正则表达式的 Hamcrest 匹配器:
verify(logMock).debug(argThat(matchesPattern("Candidate #\d+: Not syncing")));
请注意,您必须自己编写,或使用尚未包含的 PatternMatcher or hamcrest-text-patterns
as in JavaHamcrest issue #2。
Mockito 在标准 org.mockito.Matchers class 中提供正则表达式匹配器。下面是一个示例,说明如何使用此函数来验证具有正确参数值的调用:
verify(restMock, times(1)).exchange(matches(".*text=welcome.*to.*blah"), eq(HttpMethod.GET), any(ResponseEntity.class), eq(String.class));