如何在 Spring Boot with JUnit 中模拟 public 方法中的私有方法

How to mock private method in public method in Spring Boot with JUnit

请教您几个问题,请教您:

我想测试我的 public 方法(我使用 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

方法 getUserByLogingetUserListByLogin 在此 class (MyClass) 中是私有的,但我必须模拟这些私有方法的结果,因为这些方法从外部服务。 这些私有方法如下所示:

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

DelegateImpl.getDelegate().getUserByLogin 从数据库中获取数据并且必须像这样模拟数据:

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

如何测试我的 public class?我应该使用 PowerMock/PowerMockito 吗?在我看来,使这些方法 public 很难看,因为这些方法仅在 MyClass 中调用。我无法在 Internet 上为我的案例找到好的教程(Spring Boot、Mockito、JUnit)。

非常感谢您的所有提示!

此致 马修

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

稍后,在测试中,您必须注入此 class 的模拟并模拟其行为。

MyClass 在其单元测试中的设置可能与此类似:

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

AnotherClass 有方法 getUserListByLogin 和 getUserByLogin。

编辑: 您的私有方法中的逻辑似乎已经调用了外部 class。问题是您通过调用另一个 class.

中的静态 getDelegate() 方法来获取对象的实例

您可以执行以下操作:

  • MyClass 中创建一个与 getDelegate() 方法返回的类型相同的新字段(我不知道那是什么,我将其称为 Delegate)
  • 有 2 个构造函数:一个默认构造函数会将 getDelegate 方法的结果分配给您的新字段,另一个构造函数会将 Delegate 的实例作为参数并将其分配给您的字段
  • 在测试中使用第二个构造函数创建 MyClass 的实例并传递 Delegate class
  • 的模拟

它看起来或多或少像这样:

class MyClass() {
    private Delegate delegate;

    MyClass() {
        this.delegate = DelegateImpl.getDelegate();
    }

    MyClass(Delegate delegate) {
        this.delegate = delegate;
    }
    // ... the rest
}

仅通过调用 public 方法测试单元。我认为您的示例是服务层中的 class (包含业务逻辑),并且两个 getUser... 方法应该位于不同的 class (我认为在数据层中)它们可以是 public。通过构造函数将 class 作为依赖项注入(在服务对象中),这样您就可以在测试服务 class 时模拟它。数据层 class(使用 getUser... 方法)也可以通过它自己的单元测试进行测试。