Mockito:没有这样的实例方法
Mockito: No such instance method
我正在为下面给定的方法编写测试用例。
方法:
@Override
public void removeAllConnections(String uuid, String userName, String oimId) {
customLogger.debug(Thread.currentThread().getStackTrace()[1].getMethodName(), userName, null, null, accessProviderBuilder.getUserName(), accessProviderBuilder.getUuid());
UserAccessBean userAccessBean = new UserAccessBean(userName);
userAccessBean.setOimid(oimId);
userAccessBean.setToken("");
log.info("removeAllConnections:oimid:"+userAccessBean.getOimId());
UserProfileDetailBean userProfileDetail = accessClient.getAccess(userAccessBean,applicationForCsr);
Set<AccountAccess> accountAccesses = userProfileDetail.getAccountAccessList();
try {
removeAllConnectionsExceptPrimary(oimId, userName, accountAccesses);
removePrimaryConnection(oimId, userName, accountAccesses);
} catch (ConnectionStateException e) {
throw new ConnectionStateException(ConnectionNameNotRemoved, CONNECTION_REMOVAL_FAILED_MSG);
} catch (InternalServerErrorException e) {
throw new InternalServerErrorException(INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR_MSG);
}
}
下面的代码片段是给定方法的测试用例。
测试用例:
@Test
public void testRemoveAllConnections() {
UserAccessBean userAccessBean = new UserAccessBean(userName);
when(accessClient.getAccess(userAccessBean,"CSR")).thenReturn(userProfileDetail);
when(userProfileDetail.getAccountAccessList()).thenReturn(accountAccesses);
String applicaionForCSR = "CSR";
ReflectionTestUtils.setField(service, "applicationForCsr", applicaionForCSR);
service.removeAllConnections(uuid, userName, oimId);
}
调试代码时,由于 userProfileDetail 的值为 null,我的执行在给定行下方失败。
Set<AccountAccess> accountAccesses = userProfileDetail.getAccountAccessList();
在 accessClient.getAccess(userAccessBean,applicationForCsr) 上执行检查元素时抛出以下错误。很确定这是一些愚蠢的错误,但无法追踪它。
错误:
No such instance method: 'UserProfileDetailBean
v1.AccessService$$EnhancerByMockitoWithCGLIB$$a852895d.getAccess
(UserAccessBean)'
应用程序:Spring引导 1.5.0
库:Mockito 2.7.X
我可以建议三种可能的解决方案(或更像是 2.5):
a) 覆盖UserAccessBean
的equals
方法,使得两个UserAccessBeans
相等当且仅当它们的names
相等。当然,这可能会干扰您的生产代码,我不会仅仅为了测试而更改 equals 方法。
b) 由于用户名在您的测试中实际上并没有发挥重要作用(测试本身定义了用户名是什么),您可以简单地忽略细节...
when(accessClient.getAccess(Mockito.any(UserAccessBean.class),Mockito.eq("CSR"))).thenReturn(userProfileDetail);
这样,userProfileDetail 将为第一个参数的任何值 returned。当然,你在这里丢失了细节,例如,如果用户名有误,测试将是正确的,但无论如何这在你的测试中是不可能的。
Mockito.any(...)
是一个所谓的 matcher,它告诉 Mockito "use" 这个规则,无论为相关参数给出什么值。你放在那里的任何东西都可以用于 Mockito。 Mockito.eq("CSR")
告诉它,这个参数必须等于 "CSR"。所以,整个规则是...
如果有人调用accessClient.getAccess
,不管第一个参数是什么,但第二个必须等于"CSR",那么return userProfileDetail
.
所以,有了这个,第一个参数可以是任何东西。因此,例如,将接受以下呼叫:
accessClient.getAccess(new UserAccessBean("correct name"), "CSR");
accessClient.getAccess(new UserAccessBean("totally wrong name"), "CSR");
...因为第一个参数是什么并不重要,任何值都将被接受。所以,你 "lose" 有能力检查 UserAccessBean
是否正确(因为任何一个都被接受)。但是在你的情况下,因为你只在测试中定义了那些 UserAccessBeans
,所以这应该不是问题。
但如果是,我可以提供两种解决方法...
c) 使用客户匹配器(检查 UserAccessBean 的名称)或使用上面的 Mockito.any(...)
和 ArgumentCaptor 检查名称最后是否正确...
ArgumentCaptor<UserAccessBean> captor = ArgumentCaptor.forClass(UserAccessBean.class);
Mockito.verify(accessClient).getAccess(captor.capture(),Mockito.eq("CSR"));
assertEquals(captor.getValue().getName(), "myName");
我正在为下面给定的方法编写测试用例。
方法:
@Override
public void removeAllConnections(String uuid, String userName, String oimId) {
customLogger.debug(Thread.currentThread().getStackTrace()[1].getMethodName(), userName, null, null, accessProviderBuilder.getUserName(), accessProviderBuilder.getUuid());
UserAccessBean userAccessBean = new UserAccessBean(userName);
userAccessBean.setOimid(oimId);
userAccessBean.setToken("");
log.info("removeAllConnections:oimid:"+userAccessBean.getOimId());
UserProfileDetailBean userProfileDetail = accessClient.getAccess(userAccessBean,applicationForCsr);
Set<AccountAccess> accountAccesses = userProfileDetail.getAccountAccessList();
try {
removeAllConnectionsExceptPrimary(oimId, userName, accountAccesses);
removePrimaryConnection(oimId, userName, accountAccesses);
} catch (ConnectionStateException e) {
throw new ConnectionStateException(ConnectionNameNotRemoved, CONNECTION_REMOVAL_FAILED_MSG);
} catch (InternalServerErrorException e) {
throw new InternalServerErrorException(INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR_MSG);
}
}
下面的代码片段是给定方法的测试用例。
测试用例:
@Test
public void testRemoveAllConnections() {
UserAccessBean userAccessBean = new UserAccessBean(userName);
when(accessClient.getAccess(userAccessBean,"CSR")).thenReturn(userProfileDetail);
when(userProfileDetail.getAccountAccessList()).thenReturn(accountAccesses);
String applicaionForCSR = "CSR";
ReflectionTestUtils.setField(service, "applicationForCsr", applicaionForCSR);
service.removeAllConnections(uuid, userName, oimId);
}
调试代码时,由于 userProfileDetail 的值为 null,我的执行在给定行下方失败。
Set<AccountAccess> accountAccesses = userProfileDetail.getAccountAccessList();
在 accessClient.getAccess(userAccessBean,applicationForCsr) 上执行检查元素时抛出以下错误。很确定这是一些愚蠢的错误,但无法追踪它。
错误:
No such instance method: 'UserProfileDetailBean v1.AccessService$$EnhancerByMockitoWithCGLIB$$a852895d.getAccess (UserAccessBean)'
应用程序:Spring引导 1.5.0 库:Mockito 2.7.X
我可以建议三种可能的解决方案(或更像是 2.5):
a) 覆盖UserAccessBean
的equals
方法,使得两个UserAccessBeans
相等当且仅当它们的names
相等。当然,这可能会干扰您的生产代码,我不会仅仅为了测试而更改 equals 方法。
b) 由于用户名在您的测试中实际上并没有发挥重要作用(测试本身定义了用户名是什么),您可以简单地忽略细节...
when(accessClient.getAccess(Mockito.any(UserAccessBean.class),Mockito.eq("CSR"))).thenReturn(userProfileDetail);
这样,userProfileDetail 将为第一个参数的任何值 returned。当然,你在这里丢失了细节,例如,如果用户名有误,测试将是正确的,但无论如何这在你的测试中是不可能的。
Mockito.any(...)
是一个所谓的 matcher,它告诉 Mockito "use" 这个规则,无论为相关参数给出什么值。你放在那里的任何东西都可以用于 Mockito。 Mockito.eq("CSR")
告诉它,这个参数必须等于 "CSR"。所以,整个规则是...
如果有人调用accessClient.getAccess
,不管第一个参数是什么,但第二个必须等于"CSR",那么return userProfileDetail
.
所以,有了这个,第一个参数可以是任何东西。因此,例如,将接受以下呼叫:
accessClient.getAccess(new UserAccessBean("correct name"), "CSR");
accessClient.getAccess(new UserAccessBean("totally wrong name"), "CSR");
...因为第一个参数是什么并不重要,任何值都将被接受。所以,你 "lose" 有能力检查 UserAccessBean
是否正确(因为任何一个都被接受)。但是在你的情况下,因为你只在测试中定义了那些 UserAccessBeans
,所以这应该不是问题。
但如果是,我可以提供两种解决方法...
c) 使用客户匹配器(检查 UserAccessBean 的名称)或使用上面的 Mockito.any(...)
和 ArgumentCaptor 检查名称最后是否正确...
ArgumentCaptor<UserAccessBean> captor = ArgumentCaptor.forClass(UserAccessBean.class);
Mockito.verify(accessClient).getAccess(captor.capture(),Mockito.eq("CSR"));
assertEquals(captor.getValue().getName(), "myName");