Mockito - NullpointerException when stubbing Method

后端 未结 18 1549
半阙折子戏
半阙折子戏 2020-11-30 20:54

So I started writing tests for our Java-Spring-project.

What I use is JUnit and Mockito. It\'s said, that when I use the when()...thenReturn() option I can mock ser

相关标签:
18条回答
  • 2020-11-30 21:06

    The default return value of methods you haven't stubbed yet is false for boolean methods, an empty collection or map for methods returning collections or maps and null otherwise.

    This also applies to method calls within when(...). In you're example when(myService.getListWithData(inputData).get()) will cause a NullPointerException because myService.getListWithData(inputData) is null - it has not been stubbed before.

    One option is create mocks for all intermediate return values and stub them before use. For example:

    ListWithData listWithData = mock(ListWithData.class);
    when(listWithData.get()).thenReturn(item1);
    when(myService.getListWithData()).thenReturn(listWithData);
    

    Or alternatively, you can specify a different default answer when creating a mock, to make methods return a new mock instead of null: RETURNS_DEEP_STUBS

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

    You should read the Javadoc of Mockito.RETURNS_DEEP_STUBS which explains this in more detail and also has some warnings about its usage.

    I hope this helps. Just note that your example code seems to have more issues, such as missing assert or verify statements and calling setters on mocks (which does not have any effect).

    0 讨论(0)
  • 2020-11-30 21:06
    @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 {
    
     }
    }
    

    All the above commented codes are not required { mockContext = Mockito.mock(Context.class); }, if you use @Mock Annotation to Context mockContext;

    @Mock 
    Context mockContext; 
    

    But it will work if you use @RunWith(MockitoJUnitRunner.class) only. As per Mockito you can create mock object by either using @Mock or Mockito.mock(Context.class); ,

    I got NullpointerException because of using @RunWith(PowerMockRunner.class), instead of that I changed to @RunWith(MockitoJUnitRunner.class) it works fine

    0 讨论(0)
  • 2020-11-30 21:07

    Another common gotcha is that the method signature is accidentally declared as 'final'.

    This one catches out a lot of people who work on codebases which are subjected to Checkstyle and have internalised the need to mark members as final.

    i.e. in the OP's example:

    object.method()

    Make sure that method() is not declared as final:

    public final Object method() {
    }
    

    Mockito cannot mock a final method and this will come up as a wrapped NPE:

    Suppressed: org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
    

    Buried deep in the error message is the following:

    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.
    
    0 讨论(0)
  • 2020-11-30 21:08

    I had the same problem and my issue was simply that I had not annotated the class properly using @RunWith. In your example, make sure that you have:

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

    Once I did that, the NullPointerExceptions disappeared.

    0 讨论(0)
  • 2020-11-30 21:09

    When using JUnit 5 or above. You have to inject the class annotated with @Mock in an @BeforeEach setup.

    0 讨论(0)
  • 2020-11-30 21:10

    faced the same issue, the solution that worked for me:

    Instead of mocking the service interface, I used @InjectMocks to mock the service implementation:

    @InjectMocks
    private exampleServiceImpl exampleServiceMock;
    

    instead of :

    @Mock
    private exampleService exampleServiceMock;
    
    0 讨论(0)
提交回复
热议问题