Mockito: Mock private field initialization

Viewed 280764

How I can mock a field variable which is being initialized inline?

class Test {
    private Person person = new Person();
    ...
    public void testMethod() {
        person.someMethod();
        ...
    }
}

Here I want to mock person.someMethod() while testing the Test.testMethod() method for which I need to mock initialization of person variable. Any clue?

Edit: I'm not allowed to modify Person class.

8 Answers

Pretty late to the party, but I was struck here and got help from a friend. The thing was not to use PowerMock. This works with the latest version of Mockito.

Mockito comes with this org.mockito.internal.util.reflection.FieldSetter.

What it basically does is helps you modify private fields using reflection.

This is how you use it:

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
    // ...
    verify(mockedPerson).someMethod();
}

This way you can pass a mock object and then verify it later.

Here is the reference.

In case you use Spring Test try org.springframework.test.util.ReflectionTestUtils

 ReflectionTestUtils.setField(testObject, "person", mockedPerson);

Following code can be used to initialize mapper in REST client mock. The mapper field is private and needs to be set during unit test setup.

import org.mockito.internal.util.reflection.FieldSetter;

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());

if u are using spring boot test and cant find neither of WhiteBox, FeildSetter; u can simply use org.springframework.test.util.ReflectionTestUtils

this is an example:

import org.springframework.test.util.ReflectionTestUtils;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    ReflectionTestUtils.setField(underTestObject, "person", mockedPerson);
    // ...
}

Using @Jarda's guide you can define this if you need to set the variable the same value for all tests:

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

But beware that setting private values to be different should be handled with care. If they are private are for some reason.

Example, I use it, for example, to change the wait time of a sleep in the unit tests. In real examples I want to sleep for 10 seconds but in unit-test I'm satisfied if it's immediate. In integration tests you should test the real value.

The best way until now, I think that is

org.springframework.test.util.ReflectionTestUtils

Im about to mock the private String mockField in FooService.class inside FooServiceTest.java

FooService.java:

  @Value("${url.image.latest}")
  private String latestImageUrl;

FooServiceTest.java:

  @InjectMocks
  FooService service;

  @BeforeEach
  void setUp() {
    ReflectionTestUtils.setField(service, // inject into this object
        "latestImageUrl", // assign to this field
        "your value here"); // object to be injected
  }
Related