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:
Running my test cases with PowerMockRunner:
@RunWith(PowerMockRunner.class)
Instruct Powermock to prepare
Test.class
for manipulation of private fields:@PrepareForTest({ Test.class })
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
How to Send Date in Rest API in Post Method
Is There an Invisible Character That Is Not Regarded as Whitespace
How to Make Program to Continue Running After Exception
403 Forbidden When I Try to Post to My Spring API
How to Update Each Element in a List in Java 8 Using Stream API
How to Know If All the Variables in a Class Are Null
How to Set a Timeout on a Spring Boot Rest API
How to Use Variables in One Method into Another Method
How to Bypass Google Recaptcha for Testing Using Selenium
How to Upload a File and Json Data in Postman
How to Determine If a List of String Contains Null or Empty Elements
How to Pass JavaScript Values to Scriptlet in Jsp
How to Print Out All the Elements of a List in Java
Remove Duplicates from a List of Objects Based on Property in Java 8
How to Fill Hashmap from Java Property File With Spring @Value