Java Mockito-NullpointerException在存根方法时
所以我开始为我们的JavaSpring项目编写测试 我使用的是JUnit和Mockito。据说,当我使用when()…thenReturn()选项时,我可以模拟服务,而无需模拟服务。所以我想做的是,设置: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
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;