Mockito Not Mocking Private Variables Using @Spy

Mockito not mocking private variables using @Spy

myObject = new MyObject(); - this is the root of the problem. Mockito instantiates the mock for you, but you're replacing the mock with your own myObject instance, what leads to NPE (obviously, the listOfStrings is null in your newly instantiated object).

That how it should work:

@RunWith(MockitoJUnitRunner.class)
public class MyObjectTest {

// Don't do this with List!
// Type 'List' is an interface and it cannot be spied on.
@Spy
private ArrayList<String> listOfStrings;
@InjectMocks
private MyObject myObject;

@Before
public void before() {
listOfStrings.addAll(List.of("test", "test2"));
}

@Test
public void testCallListOfStrings() {
Mockito.doReturn(new ArrayList().stream()).when(listOfStrings).stream();
myObject.callListOfStrings();
}
}

Output:

test
test2

Mockito: Mock private field initialization

I already found the solution to this problem which I forgot to post here.

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Test.class })
public class SampleTest {

@Mock
Person person;

@Test
public void testPrintName() throws Exception {
PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
Test test= new Test();
test.testMethod();
}
}

Key points to this solution are:

  1. Running my test cases with PowerMockRunner: @RunWith(PowerMockRunner.class)

  2. Instruct Powermock to prepare Test.class for manipulation of private fields: @PrepareForTest({ Test.class })

  3. And finally mock the constructor for Person class:

    PowerMockito.mockStatic(Person.class);
    PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);

If I have Mockito.Spy()/@Spy doesn't work properly with FieldSetter ? How to work use @Spy and FieldSetter Combinedly?

Do not use FieldSetter, use ReflectionTestUtils.setField() and it will be fine.

Mocking member variables of a class using Mockito

You need to provide a way of accessing the member variables so you can pass in a mock (the most common ways would be a setter method or a constructor which takes a parameter).

If your code doesn't provide a way of doing this, it's incorrectly factored for TDD (Test Driven Development).

Java, Mockito: Field mocked via @InjectMocks does not notice new value written into the real variable

This is happening because on the line in Testee where myParam = new MyParam(), the reference to the class member Testee testee is reassigned to new MyParam(). The mock object in the test has not been reassigned and still points to the original value.

To resolve this, you could add setter setSomeField(String someField) to MyParam and instead of reassigning the value, in Testee, call myParam.setSomeField("a new value").

So, the mock is not able to notice a new object being written into the
mocked variable, but it does notice changes made to the object - do I
understand it correctly?

It's all about which object in memory that the reference is pointed to. In the test, we create a mock and the mocking framework sets the class member to the object reference of the mock.

We then reassign the class member but our unit test checks the mock. The mock's object reference has not been changed.



Related Topics



Leave a reply



Submit