简体   繁体   English

如何在Java中的被测类中注入被声明为private static的对象的模拟?

[英]How to inject the mock of an object which is declared as private static in the class under test in java?

I have a class ManageUser as below: 我有一个类ManageUser,如下所示:

public class ManageUser {
private static UserBO gUserBO = new UserBO();

 public String method1() {

    gUserBO.callSomeFunction();

    gUserBO.callSomeOtherFunction();

  }
}

Now, I have a test class where I want to test method1() and since the methods callSomeFunction() and callSomeOtherFunction() end up making database calls I want to mock the calls to those methods. 现在,我有一个测试类,我要在其中测试method1(),并且由于方法callSomeFunction()和callSomeOtherFunction()最终进行数据库调用,因此我想模拟对这些方法的调用。 I am unable to do that by using mock since the object in ManageUser is static. 由于ManageUser中的对象是静态的,因此无法通过模拟来做到这一点。 How do I proceed? 我该如何进行? I am new to Junit and Mockito and can't seem to find relevant answers. 我是Junit和Mockito的新手,似乎找不到相关的答案。

Try using Power Mockito: 尝试使用Power Mockito:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ManageUser.class})
public class ClassInTest {

    @Test
    public void testStatic() {
       ManageUser mUser = new ManageUser();
       Field field = PowerMockito.field(ManageUser.class, "gUserBO");
       field.set(ManageUser.class, mock(UserBO.class));
       ...
    }
}

You are "unable to do that by using mock" because your class is badly designed. 您“无法通过使用模拟做到这一点”,因为您的类设计不良。 As a workaround, you could use PowerMock (as @SK suggested) to mock the static field but that will only suppress the real problem of your class. 作为一种解决方法,您可以使用PowerMock (如@SK所建议的)模拟静态字段,但这只会抑制类的实际问题。

Better take the chance and improve the code for better testability and evolvability: 更好地把握机会并改进代码以提高可测试性和可扩展性:

Step 1: Create an interface for your class UserBO and let it implement it. 步骤1:为您的类UserBO创建一个接口,并使其实现。

public interface UserService {
    void callSomeFunction();
    void callSomeOtherFunction();
}

public class UserBO implements UserService { ... }

Step 2: Change your class ManageUser to get any implementation of UserService through a constructor. 步骤2:更改您的类ManageUser以通过构造函数获取UserService任何实现。

public class ManageUser {
    private final UserService userService;

    public ManageUser(UserService userService) {
        this.userService = userService;
    }

    public String method1() {
        userService.callSomeFunction();
        userService.callSomeOtherFunction();
    }
}

Step 3: Change the calling side of your class ManageUser to provide a UserService . 步骤3:更改类ManageUser的调用方以提供UserService

So instead of 所以代替

ManageUser manager = new ManageUser();

use 采用

ManageUser manager = new ManageUser(new UserBO());

Step 4: Now you can easily mock a UserService in your test and construct a ManageUser with the mock. 步骤4:现在,您可以轻松地在测试中模拟UserService并使用该模拟构造ManageUser


This design also enables DI frameworks (eg Spring) to inject (or autowire ) the components. 这种设计还使DI框架(例如Spring)能够注入 (或自动装配 )组件。

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

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