如何使用 mockito 为相同 class 的私有方法存根 return 值
How to stub return value for the private method of same class using mockito
我正在研究基于 spring 的项目并使用 JUnit + Mockito 编写单元测试用例。我在将布尔值存根到同一测试 class 的私有方法时遇到问题(将访问级别更改为 public 后,我仍然无法存根布尔值)。
下面的代码片段显示了相同问题的模拟
class ABC {
public String method1(User userObj){
String result = "";
if(!isValidUser(userObj.getSessionID())){
return "InvalidUser";
} else {
// execute some logic
}
return result;
}
private boolean isValidUser(String sessionId) {
// Here it calls some other class to validate the user
if (sessionId == null || UserSessionPool.getInstance().getSessionUser(sessionId) == null) {
return false;
} else {
return true;
}
}
}
在这里,我想为 method1() 编写一个测试用例。在 class ABC 中,我有一个名为 isValidUser()
的方法,它通过查看一个全局会话池来帮助识别会话中的用户,该池包含所有登录使用的详细信息,即 UserSessionPool.getInstance().getSessionUser(sessionId)
。
在测试 method1() 时,测试控制器触发 isValidUser(userObj.getSessionID())
我想从 isValidUser()
方法 return true
,这样我就可以继续测试其余的实现逻辑。
到目前为止,我已经尝试了以下方法使用间谍和模拟对象来调用 isValidUser()
方法并尝试 return true 但没有任何效果。
使用 PowerMockito
PowerMockito.doNothing().when(spyed_ABC_ClassObject, "isValidUser", true);
或
PowerMockito.doReturn(true).when(cntrl, "isValidUser", Mockito.anyString());
使用白盒
Whitebox.invokeMethod(spyed_ABC_ClassObject, "isValidUser", Mockito.anyString());
使用Mockito.when
when(spyed_ABC_ClassObject.isValidUser(Mockito.anyString())).thenReturn(true);
或
Mockito.doNothing().when(spyed_ABC_ClassObject).isValidUser(Mockito.anyString());
你能试试这个吗?
@Before
public void setUp() {
UserSessionPool mockConnectionPool = Mockito.mock(UserSessionPool.class);
}
@Test
public void testName() throws Exception {
//given
PowerMockito.mockStatic(UserSessionPool.class);
BDDMockito.given(UserSessionPool.getInstance()(...)).willReturn(mockConnectionPool);
Mockito.when(mockConnectionPool.getSessionUser(Mockito.anylong())).thenReturn(something);
//then
PowerMockito.verifyStatic();
}
希望这对您有所帮助。编码愉快!
另一个答案是:修正你的设计,而不是转向大的 PowerMock 锤子。
是的,PowerMock 允许您mock 静态方法。但是你应该明白:static是好的OO设计中的异常。只有当你有充分的理由时,你才会使用它。因为它会导致您的 类 之间 紧密 耦合,并且令人惊讶:它 破坏 您编写合理的单元测试的能力。是的,PowerMock 有效;但有时,事实并非如此。当你的 类 成长,你做的事情越来越多 "statically",因为,你知道,PowerMock 会做这个工作......在某些时候为奇怪的失败做好准备,这可能需要几个小时才能找到吃下;从未在您的生产代码中发现真正的错误。
所以,考虑一个替代方案:
- 不要使用静态方法调用。如果周围有一些您无法触及的静态方法;考虑围绕它构建一个小界面。
- 相反:使用依赖项注入并简单地将实现某些接口的对象传递到您的生产代码中。因为你可以模拟这样的对象 而不需要 PowerMock(ito).
从这个意义上说:您只是创建了难以测试 的代码。现在您打算使用 PowerMock 修复该问题。另一种方式(在我看来更合理)是首先学习如何编写 testable 代码。 Here 是一个很好的起点。
我正在研究基于 spring 的项目并使用 JUnit + Mockito 编写单元测试用例。我在将布尔值存根到同一测试 class 的私有方法时遇到问题(将访问级别更改为 public 后,我仍然无法存根布尔值)。
下面的代码片段显示了相同问题的模拟
class ABC {
public String method1(User userObj){
String result = "";
if(!isValidUser(userObj.getSessionID())){
return "InvalidUser";
} else {
// execute some logic
}
return result;
}
private boolean isValidUser(String sessionId) {
// Here it calls some other class to validate the user
if (sessionId == null || UserSessionPool.getInstance().getSessionUser(sessionId) == null) {
return false;
} else {
return true;
}
}
}
在这里,我想为 method1() 编写一个测试用例。在 class ABC 中,我有一个名为 isValidUser()
的方法,它通过查看一个全局会话池来帮助识别会话中的用户,该池包含所有登录使用的详细信息,即 UserSessionPool.getInstance().getSessionUser(sessionId)
。
在测试 method1() 时,测试控制器触发 isValidUser(userObj.getSessionID())
我想从 isValidUser()
方法 return true
,这样我就可以继续测试其余的实现逻辑。
到目前为止,我已经尝试了以下方法使用间谍和模拟对象来调用 isValidUser()
方法并尝试 return true 但没有任何效果。
使用 PowerMockito
PowerMockito.doNothing().when(spyed_ABC_ClassObject, "isValidUser", true);
或
PowerMockito.doReturn(true).when(cntrl, "isValidUser", Mockito.anyString());
使用白盒
Whitebox.invokeMethod(spyed_ABC_ClassObject, "isValidUser", Mockito.anyString());
使用Mockito.when
when(spyed_ABC_ClassObject.isValidUser(Mockito.anyString())).thenReturn(true);
或
Mockito.doNothing().when(spyed_ABC_ClassObject).isValidUser(Mockito.anyString());
你能试试这个吗?
@Before
public void setUp() {
UserSessionPool mockConnectionPool = Mockito.mock(UserSessionPool.class);
}
@Test
public void testName() throws Exception {
//given
PowerMockito.mockStatic(UserSessionPool.class);
BDDMockito.given(UserSessionPool.getInstance()(...)).willReturn(mockConnectionPool);
Mockito.when(mockConnectionPool.getSessionUser(Mockito.anylong())).thenReturn(something);
//then
PowerMockito.verifyStatic();
}
希望这对您有所帮助。编码愉快!
另一个答案是:修正你的设计,而不是转向大的 PowerMock 锤子。
是的,PowerMock 允许您mock 静态方法。但是你应该明白:static是好的OO设计中的异常。只有当你有充分的理由时,你才会使用它。因为它会导致您的 类 之间 紧密 耦合,并且令人惊讶:它 破坏 您编写合理的单元测试的能力。是的,PowerMock 有效;但有时,事实并非如此。当你的 类 成长,你做的事情越来越多 "statically",因为,你知道,PowerMock 会做这个工作......在某些时候为奇怪的失败做好准备,这可能需要几个小时才能找到吃下;从未在您的生产代码中发现真正的错误。
所以,考虑一个替代方案:
- 不要使用静态方法调用。如果周围有一些您无法触及的静态方法;考虑围绕它构建一个小界面。
- 相反:使用依赖项注入并简单地将实现某些接口的对象传递到您的生产代码中。因为你可以模拟这样的对象 而不需要 PowerMock(ito).
从这个意义上说:您只是创建了难以测试 的代码。现在您打算使用 PowerMock 修复该问题。另一种方式(在我看来更合理)是首先学习如何编写 testable 代码。 Here 是一个很好的起点。