Mockito 不使用@Spy 模拟私有变量
Mockito not mocking private variables using @Spy
我正在尝试使用 Mockito 的 @Spy
注释模拟私有实例变量 listOfStrings
。
@RunWith(MockitoJUnitRunner.class)
public class MyObjectTest {
@InjectMocks
MyObject myObject;
@Spy
List<String> listOfStrings;
@Before
public void before() {
myObject = new MyObject();
}
@Test
public void testCallListOfStrings() {
Mockito.doReturn(new ArrayList().stream()).when(listOfStrings).stream();
myObject.callListOfStrings();
}
}
和
public class MyObject {
private List<String> listOfStrings;
public void callListOfStrings() {
listOfStrings.stream().forEach(System.out::println);
}
}
它似乎不是在模拟实例变量,显然是抛出一个 NullPointerException
。
您忘记在 before()
中调用 Mockito.initMocks(this)
。另外,您不需要初始化 myObject
因为 mockito
会为您初始化它。
我还想指出,您的测试实际上没有做任何事情,因为您没有断言或验证任何事情,您只是调用 MyObject.call ListOfString()
方法。
您是否尝试过使用 Java 反射。我认为你需要避免空指针异常。
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;
import java.lang.reflect.Field;
import java.util.ArrayList;
@RunWith(MockitoJUnitRunner.class)
public class MyObjectTest {
@InjectMocks
MyObject myObject;
@Before
public void before() {
myObject = new MyObject();
}
@Test
public void testCallListOfStrings() throws NoSuchFieldException, IllegalAccessException {
Field list = myObject.getClass().getDeclaredField("listOfStrings");
list.setAccessible(true); // Suppress Java language access checking
list.set(myObject,new ArrayList<>());
myObject.callListOfStrings();
}
}
您可以为私有变量赋值
listOfStrings
这将避免空指针异常。
myObject = new MyObject();
- 这是问题的根源。 Mockito
为您实例化模拟,但您要用自己的 myObject
实例替换模拟,这会导致 NPE(显然,listOfStrings
在新实例化的对象中为 null)。
它应该如何工作:
@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();
}
}
输出:
test
test2
我正在尝试使用 Mockito 的 @Spy
注释模拟私有实例变量 listOfStrings
。
@RunWith(MockitoJUnitRunner.class)
public class MyObjectTest {
@InjectMocks
MyObject myObject;
@Spy
List<String> listOfStrings;
@Before
public void before() {
myObject = new MyObject();
}
@Test
public void testCallListOfStrings() {
Mockito.doReturn(new ArrayList().stream()).when(listOfStrings).stream();
myObject.callListOfStrings();
}
}
和
public class MyObject {
private List<String> listOfStrings;
public void callListOfStrings() {
listOfStrings.stream().forEach(System.out::println);
}
}
它似乎不是在模拟实例变量,显然是抛出一个 NullPointerException
。
您忘记在 before()
中调用 Mockito.initMocks(this)
。另外,您不需要初始化 myObject
因为 mockito
会为您初始化它。
我还想指出,您的测试实际上没有做任何事情,因为您没有断言或验证任何事情,您只是调用 MyObject.call ListOfString()
方法。
您是否尝试过使用 Java 反射。我认为你需要避免空指针异常。
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;
import java.lang.reflect.Field;
import java.util.ArrayList;
@RunWith(MockitoJUnitRunner.class)
public class MyObjectTest {
@InjectMocks
MyObject myObject;
@Before
public void before() {
myObject = new MyObject();
}
@Test
public void testCallListOfStrings() throws NoSuchFieldException, IllegalAccessException {
Field list = myObject.getClass().getDeclaredField("listOfStrings");
list.setAccessible(true); // Suppress Java language access checking
list.set(myObject,new ArrayList<>());
myObject.callListOfStrings();
}
}
您可以为私有变量赋值
listOfStrings
这将避免空指针异常。
myObject = new MyObject();
- 这是问题的根源。 Mockito
为您实例化模拟,但您要用自己的 myObject
实例替换模拟,这会导致 NPE(显然,listOfStrings
在新实例化的对象中为 null)。
它应该如何工作:
@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();
}
}
输出:
test
test2