简体   繁体   English

如何使用mockito存根同一类的私有方法的返回值

[英]How to stub return value for the private method of same class using mockito

I am working on spring based project and writing unit test case using JUnit + Mockito.我正在研究基于 spring 的项目并使用 JUnit + Mockito 编写单元测试用例。 I am facing a problem while stubbing boolean value to a private method of same test class (after changing access level to public, still I have failed to stub the boolean value).我在将布尔值存根到同一测试类的私有方法时遇到问题(在将访问级别更改为公共后,我仍然无法存根布尔值)。

Below code snippet shows the simulation of same problem下面的代码片段显示了相同问题的模拟

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;
        }
    } 
}

Here, I would like to write a test case for method1().在这里,我想为method1()编写一个测试用例。 In class ABC I have a method called isValidUser() which helps to identify the user with in a session by looking into a global session pool which holds all logged-in used details ie UserSessionPool.getInstance().getSessionUser(sessionId) .在 ABC 类中,我有一个名为isValidUser()的方法,它通过查看全局会话池来帮助识别会话中的用户,该池包含所有登录使用的详细信息,即UserSessionPool.getInstance().getSessionUser(sessionId)

While testing method1(), the moment test controller triggers isValidUser(userObj.getSessionID()) I would like to return true from isValidUser() method, so that I can continue to test rest of the implementation logic.在测试 method1() 时,当测试控制器触发isValidUser(userObj.getSessionID())我想从isValidUser()方法返回true ,以便我可以继续测试其余的实现逻辑。

So far I have tried following ways using spy and mocked object to call the isValidUser() method and try to return true but nothing worked well.到目前为止,我已经尝试使用 spy 和isValidUser()对象来调用isValidUser()方法并尝试返回 true 但没有任何效果。

Using PowerMockito使用 PowerMockito

PowerMockito.doNothing().when(spyed_ABC_ClassObject, "isValidUser", true);

or或者

PowerMockito.doReturn(true).when(cntrl, "isValidUser", Mockito.anyString());

Using Whitebox使用白盒

Whitebox.invokeMethod(spyed_ABC_ClassObject, "isValidUser", Mockito.anyString());

Using Mockito.when使用 Mockito.when

when(spyed_ABC_ClassObject.isValidUser(Mockito.anyString())).thenReturn(true);

or或者

Mockito.doNothing().when(spyed_ABC_ClassObject).isValidUser(Mockito.anyString());

The other answer is: fix your design instead of turning to the big PowerMock hammer.另一个答案是:修复您的设计,而不是求助于 PowerMock 的大锤子。

Yes, PowerMock allows you to mock static methods.是的,PowerMock 允许您模拟静态方法。 But you should understand: static is an abnormality in good OO design.但是你应该明白:静态是好的 OO 设计中的一个异常 You only use it when you have very good reasons.只有当你有很好的理由时才使用它。 As it leads to tight coupling between your classes, and surprise: it breaks your ability to write reasonable unit tests.因为它会导致您的类之间的紧密耦合,令人惊讶的是:它破坏了您编写合理单元测试的能力。 Yes, PowerMock works;是的,PowerMock 有效; but sometimes, it does not.但有时,事实并非如此。 When your classes grow, and you do more and more things "statically", because, you know, PowerMock will do the job ... be prepared for bizarre fails at some point, that can take hours to hunt down;当你的班级增长,你“静态地”做越来越多的事情,因为,你知道,PowerMock 会完成这项工作......在某些时候为奇怪的失败做好准备,这可能需要几个小时才能找到; without ever finding real bugs in your production code.永远不会在您的生产代码中发现真正的错误。

So, consider an alternative:所以,考虑一个替代方案:

  1. Do not use static method calls.不要使用静态方法调用。 And if there is some static method around that you can't touch;如果周围有一些您无法触及的静态方法; consider building a small interface around that.考虑围绕它构建一个小界面。
  2. Instead: use dependency injection and simply pass objects implementing some interface into your production code.相反:使用依赖注入并简单地将实现某些接口的对象传递到您的生产代码中。 Because you can mock such objects without the need for PowerMock(ito).因为您可以在不需要 PowerMock(ito) 的情况下模拟此类对象。

In that sense: you simply created hard to test code.从这个意义上说:您只是创建了难以测试的代码。 Now you intend to fix that using PowerMock.现在您打算使用 PowerMock 修复该问题。 The other way (much more reasonable in my eyes) is to learn how to write testable code in the first place.另一种方式(在我看来更合理)是首先学习如何编写可测试的代码。 Here is a good starting point for that.是一个很好的起点。

Can you please try this out.你能试试这个吗。

@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();

}

Hope this helps.希望这可以帮助。 Happy coding !快乐编码!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM