Mockito没有使用@Spy来模拟私有变量

时间:2018-05-15 16:46:02

标签: java mockito spy

我正在尝试使用Mockito的listOfStrings注释来模拟私有实例变量@Spy

@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

3 个答案:

答案 0 :(得分:1)

myObject = new MyObject(); - 这是问题的根源。 Mockito为你实例化了mock,但是你用自己的myObject实例替换了mock,导致了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

答案 1 :(得分:0)

您忘记在Mockito.initMocks(this)内拨打before()了。此外,您不需要初始化myObject,因为mockito会为您初始化它。

我还要注意,您的测试确实没有做任何事情,因为您没有断言或验证任何内容,而您只是调用MyObject.call ListOfString()方法。

答案 2 :(得分:0)

您是否尝试使用Java Reflection。我认为你需要避免空指针异常。

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

这将避免空指针异常。