简体   繁体   中英

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:

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. I am unable to do that by using mock since the object in ManageUser is static. How do I proceed? I am new to Junit and Mockito and can't seem to find relevant answers.

Try using 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.

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.

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.

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 .

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.


This design also enables DI frameworks (eg Spring) to inject (or autowire ) the components.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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