簡體   English   中英

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

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.initMocks(this)內部調用Mockito.initMocks(this) before() 另外,您不需要初始化myObject因為mockito會為您初始化它。

我還要指出的是,您的測試實際上並沒有做任何事情,因為您沒有斷言或驗證任何事情,您只是在調用MyObject.call ListOfString()方法。

您是否嘗試過使用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

這樣可以避免空指針異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM