代码之家  ›  专栏  ›  技术社区  ›  Matelutex

如何用JUnit模拟Spring引导中的私有方法

  •  0
  • Matelutex  · 技术社区  · 6 年前

    我想让你问几个问题并征求你的意见:

    我想测试我的公共方法(我使用Spring Boot、Mockito、Junit):

    @Service
    public class MyClass{
    
    public Long getClientId(List<String> nameSurname) throws AuthorizationException {
            Long operatorId;
            if(...){
            (... something not interesting ...)
                User user = getUserByLogin("AnthonyGates2");
                operatorId = nonNull(user) ? user.getOperatorId() : null;
            } else {
                List<User> users = getUserListByLogin("AnthinyGates");
                operatorId = isNotEmpty(users) ? return operatorId;
             return operatorId;
        }
    

    如何测试方法 getClientId ?

    方法 getUserByLogin getUserListByLogin 在这个班是私人的( MyClass )但是我不得不模拟这些私有方法的结果,因为这些方法从外部服务检索数据。 这些私有方法如下:

    User user = DelegateImpl.getDelegate().getUserByLogin(nameAndSurname);
    

    delegateimpl.getdelegate().getuserbylogin从数据库获取数据,必须模拟该数据,如下所示:

    when(DelegateImpl.getDelegate().getUserByLogin(any())).thenReturn(user);
    

    我如何测试我的公共课?我应该使用powermock/powermockito吗?在我看来,公开这些方法很难看,因为这些方法只在 类名 . 我在互联网上找不到适合我案例的好教程(SpringBoot,Mockito,Junit)。

    非常感谢您的所有提示!

    顺祝商祺! 马修

    2 回复  |  直到 6 年前
        1
  •  1
  •   Poger    6 年前

    如果您不能对一个方法/类进行单元测试,那么它很可能意味着它做的太多了。尝试将私有方法提取到单独的类中。它不需要是公共的-例如,您可以将它的包放在同一个包中的本地包中。

    稍后,在测试中,您将不得不注入这个类的模拟并模拟它的行为。

    myClass在其单元测试中的设置可能类似于:

    AnotherClass anotherClassMock = Mockito.mock(AnotherClass.class);
    MyClass myClass = new MyClass(anotherClassMock);
    

    其中,其他类将具有方法getUserListByLogin和getUserByLogin。

    编辑: 似乎私有方法中的逻辑已经调用了外部类。问题是,通过调用静态对象来获取对象的实例 getDelegate() 其他类中的方法。

    您可以这样做:

    • 在中创建新字段 MyClass 与返回的类型相同 获取委托() 方法(我不知道那是什么,我会叫它 Delegate )
    • 有两个构造函数:一个默认的构造函数,它将分配 getDelegate 方法来创建新字段和另一个 代表 作为参数并将其分配给您的字段
    • 在测试中,使用第二个构造函数创建 类名 并通过模拟 代表

    看起来更不像这样:

    class MyClass() {
        private Delegate delegate;
    
        MyClass() {
            this.delegate = DelegateImpl.getDelegate();
        }
    
        MyClass(Delegate delegate) {
            this.delegate = delegate;
        }
        // ... the rest
    }
    
        2
  •  1
  •   Jasper Huzen    6 年前

    仅通过调用公共方法测试单元。我认为您的示例是服务层中的一个类(包含业务逻辑)和两个getuser…方法应该在不同的类(我认为在数据层中)中,它们可以是公共的。通过构造函数将该类作为依赖项(在服务对象中)注入,以便在测试服务类时模拟它。数据层类(使用getuser…方法)也可以通过自己的单元测试进行测试。