Java Mockito-NullpointerException在存根方法时

Java Mockito-NullpointerException在存根方法时,java,testing,junit,mockito,stubbing,Java,Testing,Junit,Mockito,Stubbing,所以我开始为我们的JavaSpring项目编写测试 我使用的是JUnit和Mockito。据说,当我使用when()…thenReturn()选项时,我可以模拟服务,而无需模拟服务。所以我想做的是,设置: when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass) 但无论我使用哪个when子句,我总是得到一个NullpointerExc

所以我开始为我们的JavaSpring项目编写测试

我使用的是JUnit和Mockito。据说,当我使用when()…thenReturn()选项时,我可以模拟服务,而无需模拟服务。所以我想做的是,设置:

when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass)  
但无论我使用哪个when子句,我总是得到一个NullpointerException,这当然是有意义的,因为输入是null的

此外,当我尝试从对象模拟另一个方法时:

when(object.method()).thenReturn(true)
在那里我还得到一个空指针,因为该方法需要一个未设置的变量

但是我想使用when()…thenReturn()来创建这个变量等等。我只是想确保,如果有任何类调用这个方法,那么不管发生什么,只要返回true或上面的列表

这基本上是我一方的误解,还是有其他问题

代码:

public class classIWantToTest implements classIWantToTestFacade{
        @Autowired
        private SomeService myService;

        @Override
        public Optional<OutputData> getInformations(final InputData inputData) {
            final Optional<OutputData> data = myService.getListWithData(inputData);
            if (data.isPresent()) {
                final List<ItemData> allData = data.get().getItemDatas();
                    //do something with the data and allData
                return data;
            }

            return Optional.absent();
        }   
}
公共类ClassWantTest实现ClassWantTestFacade{
@自动连线
私人服务myService;
@凌驾
公共可选GetInformation(最终输入数据输入数据){
最终可选数据=myService.getListWithData(inputData);
if(data.isPresent()){
最终列表allData=data.get().getItemDatas();
//对数据和所有数据进行处理
返回数据;
}
返回可选的。缺席();
}   
}
这是我的测试课:

public class Test {

    private InputData inputdata;

    private ClassUnderTest classUnderTest;

    final List<ItemData> allData = new ArrayList<ItemData>();

    @Mock
    private DeliveryItemData item1;

    @Mock
    private DeliveryItemData item2;



    @Mock
    private SomeService myService;


    @Before
    public void setUp() throws Exception {
        classUnderTest = new ClassUnderTest();
        myService = mock(myService.class); 
        classUnderTest.setService(myService);
        item1 = mock(DeliveryItemData.class);
        item2 = mock(DeliveryItemData.class);

    }


    @Test
    public void test_sort() {
        createData();
        when(myService.getListWithData(inputdata).get().getItemDatas());

        when(item1.hasSomething()).thenReturn(true);
        when(item2.hasSomething()).thenReturn(false);

    }

    public void createData() {
        item1.setSomeValue("val");
        item2.setSomeOtherValue("test");

        item2.setSomeValue("val");
        item2.setSomeOtherValue("value");

        allData.add(item1);
        allData.add(item2);


}
公共类测试{
私有输入数据输入数据;
私有类被测类被测;
最终列表allData=new ArrayList();
@嘲弄
私人递送项目数据项目1;
@嘲弄
私人递送项目数据项目2;
@嘲弄
私人服务myService;
@以前
public void setUp()引发异常{
classUnderTest=新的classUnderTest();
myService=mock(myService.class);
classUnderTest.setService(myService);
item1=mock(DeliveryItemData.class);
item2=mock(DeliveryItemData.class);
}
@试验
公共无效测试_sort(){
createData();
when(myService.getListWithData(inputdata.get().getItemDatas());
when(item1.hasSomething())。然后返回(true);
when(item2.hasSomething())。然后返回(false);
}
public void createData(){
项目1.设定总价值(“val”);
项目2.设置其他值(“测试”);
项目2.设定总价值(“val”);
项目2.设置其他价值(“价值”);
添加所有数据(第1项);
添加所有数据(第2项);
}

对于布尔方法,尚未存根的方法的默认返回值为
false
,对于返回集合或映射的方法,为空集合或映射,否则为
null

这也适用于
when(…)
中的方法调用。例如
when(myService.getListWithData(inputData).get())
将导致NullPointerException,因为
myService.getListWithData(inputData)
null
-它以前没有被存根过

一个选项是为所有中间返回值创建模拟,并在使用前将其存根。例如:

ListWithData listWithData = mock(ListWithData.class);
when(listWithData.get()).thenReturn(item1);
when(myService.getListWithData()).thenReturn(listWithData);
或者,您也可以在创建模拟时指定不同的默认答案,以使方法返回新的模拟而不是null:
返回\u DEEP\u存根

SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS);
when(myService.getListWithData().get()).thenReturn(item1);
您应该阅读Javadoc,它更详细地解释了这一点,并对其用法提出了一些警告


我希望这能有所帮助。请注意,您的示例代码似乎有更多问题,例如缺少assert或verify语句,以及在Mock上调用setter(这没有任何效果)。

我也有同样的问题,我的问题只是没有使用@RunWith正确注释类。在您的示例中,请确保您有:

@RunWith(MockitoJUnitRunner.class)
public class Test {
...

一旦我这样做,NullPointerException就消失了。

我遇到了这个问题,我的问题是我用
any()
调用我的方法,而不是
anyInt()
。因此我有:

doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any())
我不得不把它改成:

doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt())
我不知道为什么会产生一个空点异常。也许这会帮助下一个可怜的灵魂

@RunWith(MockitoJUnitRunner.class) //(OR) PowerMockRunner.class

@PrepareForTest({UpdateUtil.class,Log.class,SharedPreferences.class,SharedPreferences.Editor.class})
public class InstallationTest extends TestCase{

@Mock
Context mockContext;
@Mock
SharedPreferences mSharedPreferences;
@Mock
SharedPreferences.Editor mSharedPreferenceEdtor;

@Before
public void setUp() throws Exception
{
//        mockContext = Mockito.mock(Context.class);
//        mSharedPreferences = Mockito.mock(SharedPreferences.class);
//        mSharedPreferenceEdtor = Mockito.mock(SharedPreferences.Editor.class);
    when(mockContext.getSharedPreferences(Mockito.anyString(),Mockito.anyInt())).thenReturn(mSharedPreferences);
    when(mSharedPreferences.edit()).thenReturn(mSharedPreferenceEdtor);
    when(mSharedPreferenceEdtor.remove(Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
    when(mSharedPreferenceEdtor.putString(Mockito.anyString(),Mockito.anyString())).thenReturn(mSharedPreferenceEdtor);
}

@Test
public void deletePreferencesTest() throws Exception {

 }
}
以上所有注释代码都不是必需的 {
mockContext=Mockito.mock(Context.class);
}, 如果使用@Mock注释到
上下文mockContext;

@Mock 
Context mockContext; 
但是,如果您仅使用@RunWith(MockitoJUnitRunner.class),它将起作用。根据Mockito,您可以使用@mock或Mockito.mock(Context.class)


由于使用@RunWith(PowerMockRunner.class),我得到了NullpointerException,而不是改为@RunWith(MockitoJUnitRunner.class),它工作正常 如果您使用的是Scala,并且尝试在值类上创建
任何
匹配器,您将得到一个没有帮助的NPE

因此,给定
case类ValueClass(value:Int)扩展AnyVal
,您要做的是
ValueClass(anyInt)
,而不是
any[ValueClass]

when(mock.someMethod(ValueClass(anyInt))).thenAnswer {
   ...
   val v  = ValueClass(invocation.getArguments()(0).asInstanceOf[Int])
   ...
}

另一个更具体地说是关于这一点的,但是当你不知道问题出在值类上时,你会错过它。

对我来说,我得到NPE的原因是我在模拟原语时使用了
Mockito.any()
。我发现,通过切换到使用正确的Mockito变体,可以消除错误

例如,要模拟一个以原语
long
为参数的函数,而不是使用
any()
,您应该更加具体,并将其替换为
any(long.class)
Mockito.anyLong()


希望这对某人有所帮助。

面对同样的问题,我的解决方案是:

我没有模拟服务接口,而是使用@InjectMocks模拟服务实现:

@InjectMocks
private exampleServiceImpl exampleServiceMock;
而不是:

@Mock
private exampleService exampleServiceMock;

对于未来的读者来说,使用mock时NPE的另一个原因是忘记初始化mock,如
@Mock
SomeMock someMock;

@InjectMocks
SomeService someService;

@Before
public void setup(){
    MockitoAnnotations.initMocks(this); //without this you will get NPE
}

@Test
public void someTest(){
    Mockito.when(someMock.someMethod()).thenReturn("some result");
   // ...
}
  @Rule public Mocks mocks = new Mocks(this);
PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);
java.lang.NullPointerException
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:42)
    at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.when(PowerMockitoStubberImpl.java:112)
   @Before public void initMocks() {
       MockitoAnnotations.initMocks(this);
   }
@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}
@BeforeEach
public void setup() {
    MockitoAnnotations.initMocks(this);
}
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public final Object method() {
}
Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
 public Boolean getResult(String identifier, boolean switch)
 public Boolean getResult(String identifier, Boolean switch)
import org.junit.jupiter.api.Test;
@ExtendWith(MockitoExtension.class)
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;