Mockito – 存根方法时的NullpointerException

所以我开始为Java-Spring项目编写测试。

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

when(classIwantToTest.object.get().methodWhichReturnsAList(input))thenReturn(ListcreatedInsideTheTestClass) 

但无论我在哪个when子句中,我总是得到一个NullpointerException,当然这是有道理的,因为输入是null。

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

 when(object.method()).thenReturn(true) 

在那里我也得到一个Nullpointer,因为该方法需要一个未设置的变量。

但我想使用when().. thenReturn()来绕过创建这个变量等等。 我只是想确保,如果任何类调用此方法,那么无论如何,只返回true或上面的列表。

这是我身边的一个基本误解,还是有其他错误?

码:

 public class classIWantToTest implements classIWantToTestFacade{ @Autowired private SomeService myService; @Override public Optional getInformations(final InputData inputData) { final Optional data = myService.getListWithData(inputData); if (data.isPresent()) { final List allData = data.get().getItemDatas(); //do something with the data and allData return data; } return Optional.absent(); } } 

这是我的测试类:

 public class Test { private InputData inputdata; private ClassUnderTest classUnderTest; final List allData = new ArrayList(); @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); } 

对于布尔方法,尚未存根的方法的默认返回值为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: RETURNS_DEEP_STUBS

 SomeService myService = mock(SomeService.class, Mockito.RETURNS_DEEP_STUBS); when(myService.getListWithData().get()).thenReturn(item1); 

您应该阅读Mockito.RETURNS_DEEP_STUBS的Javadoc,它更详细地解释了这一点,并且还有一些关于它的用法的警告。

我希望这有帮助。 请注意,您的示例代码似乎有更多问题,例如缺少断言或validation语句以及在模拟上调用setter(这没有任何影响)。

我有这个问题,我的问题是我用any()而不是anyInt()调用我的方法。 所以我有:

 doAnswer(...).with(myMockObject).thisFuncTakesAnInt(any()) 

我不得不把它改成:

 doAnswer(...).with(myMockObject).thisFuncTakesAnInt(anyInt()) 

我不知道为什么会产生NullPointerException。 也许这将有助于下一个可怜的灵魂。

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

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

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

转角案例:
如果您正在使用Scala并尝试在值类上创建any匹配器,那么您将获得无用的NPE。

因此,给定case class ValueClass(value: Int) extends AnyVal ,你想要做的是ValueClass(anyInt)而不是any[ValueClass]

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

另外这个问题更具体地讲述了这个问题,但是当你不知道问题与价值类别有关时,你会想念它。

对我而言,我获得NPE的原因是我在Mockito.any()基元时使用Mockito.any() 。 我发现通过切换到使用mockito的正确变体来摆脱错误。

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

希望能帮助别人。

干杯

 @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 Annotation到Context mockContext;

  @Mock Context mockContext; 

但是如果你只使用@RunWith(MockitoJUnitRunner.class)它会工作。 根据Mockito,您可以使用@Mock或Mockito.mock(Context.class)创建模拟对象;

因为使用了@RunWith(PowerMockRunner.class),我得到了NullpointerException,而不是我改为@RunWith(MockitoJUnitRunner.class)它工作正常

对于未来的读者来说,使用模拟时NPE的另一个原因是忘记初始化模拟,如下所示:

 @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"); // ... } 

面对同样的问题,这个解决方案对我有用:

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

 @InjectMocks private exampleServiceImpl exampleServiceMock; 

代替 :

 @Mock private exampleService exampleServiceMock; 

在我的案例中,Ed Webb的答案有所帮助。 相反,您也可以尝试添加

  @Rule public Mocks mocks = new Mocks(this); 

如果你@RunWith(JUnit4.class)

在我的情况下,我错过了先添加

 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)