user5417542
user5417542

Reputation: 3376

Mockito - NullpointerException when stubbing Method

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 services, without simulating them or so. So what I want to do is, to set:

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

But no matter which when-clause I do, I always get a NullpointerException, which of course makes sense, because input is null.

Also when I try to mock another method from an object:

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

There I also get a Nullpointer, because the method needs a variable, which isn't set.

But I want to use when()..thenReturn() to get around creating this variable and so on. I just want to make sure, that if any class calls this method, then no matter what, just return true or the list above.

Is it a basically misunderstanding from my side, or is there something else wrong?

Code:

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();
        }   
}

And here is my test class:

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);


}

Upvotes: 195

Views: 422300

Answers (30)

Assaduzzaman Assad
Assaduzzaman Assad

Reputation: 77

Fix Static Import

Please check the static import. It seems like this is the issue.

The correct import should be:

import static org.mockito.Mockito.when

Instead of:

import static reactor.core.publisher.Mono.when.

Upvotes: 1

8bitjunkie
8bitjunkie

Reputation: 13245

Check that the method signature is not 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.

Upvotes: 5

mitesh keswani
mitesh keswani

Reputation: 153

I was using wrong annotation/import of Mock, so my object was not getting formed. I was using org.evosuite.shaded.org.mockito.Mock and I switched back to org.mockito.Mock. Then as if by magic, it started working for me.

Upvotes: 1

Shurion
Shurion

Reputation: 1

In my case UnderTest class has two kind of injections: via constructor(TheSecondService) and via setters(TheFirstService).

All injections via setters was null. This helps:

@Mock
private TheFirstService theFirstService;
@Mock
private TheSecondService theSecondService;
@InjectMocks
private TheThirdService underTest;
  
@BeforeEach
public void setup() {
    underTest.setTheFirstService(theFirstService);
}

Upvotes: 0

noobie2023
noobie2023

Reputation: 783

In my case, my Mockito annotation didn't match the JUnit Version.

  1. When using @ExtendWith(MockitoExtension.class) make sure you're using JUnit 5: import org.junit.jupiter.api.Test;

  2. When using @RunWith(MockitoJUnitRunner.class) make sure you're using JUnit 4: import org.junit.Test;

Upvotes: 4

tommytucker7182
tommytucker7182

Reputation: 243

This doesnt answer the OP's original query, but its here to try help others with Mockito null pointer exceptions (NPE).

My NPE was happening as I did not explicitly set the class under tests' dependencies to be the classes I had mocked. So the class under test was unable to find its required dependencies, creating the NPE. I tend to not mock the class under test (i.e. use new keyword), to ensure im getting my native class behaviour for testing.

Im still using Junit 4 for reasons outside my control. Worked example;

ClassUnderTest

public class ClassUnderTest {
    private DependantClassOne dependantClassOne; 
    private DependantClassTwo dependantClassTwo;

    // remaining class, including setters
}

Test Class

@RunWith(MockitoJUnitRunner.class)
public class Test {
    private ClassUnderTest classUnderTest;
    private DependantClassOne dependantClassOne;
    private DependantClassTwo dependantClassTwo;
 
    @Before
    public void setup() {
        dependantClassOne = mock(DependantClassOne.class);
        dependantClassTwo = mock(DependantClassTwo.class);
        classUnderTest = new ClassUnderTest();

        classUnderTest.setDependantClassOne(dependantClassOne); //added to prevent NPE
        classUnderTest.setDependantClassTwo(dependantClassTwo); //added to prevent NPE
    }

    // tests
}

Upvotes: 0

Tanel
Tanel

Reputation: 1500

As this is the closest I found to the issue I had, it's the first result that comes up and I didn't find an appropriate answer, I'll post the solution here for any future poor souls:

any() doesn't work where mocked class method uses a primitive parameter.

 public Boolean getResult(String identifier, boolean switch)

The above will produce the same exact issue as OP.

Solution, just wrap it:

 public Boolean getResult(String identifier, Boolean switch)

The latter solves the NPE.

  • keep in mind if you choose this approach, now you might want to include a nullcheck for Boolean in production code (credit: brought up by Ridcully)

Upvotes: 20

passive_programmer
passive_programmer

Reputation: 1

Check which version of Junit you are using. In the Maven/Gradle build tool, if you set to use testRuntimeOnly 'junit5',then it might not take @RunWith since it is not available and it is replaced with @ExtendWith in Junit5.

Upvotes: 0

Spencer Sutton
Spencer Sutton

Reputation: 3397

I was trying to mock a "final" method, which apparently was the problem.

The right way to handle this would be to use an interface and mock that interface however I couldn't control the library where the "final" method was.

Mockito 2 can handle mocking final method. Add a text file to the project's src/test/resources/mockito-extensions directory named org.mockito.plugins.MockMaker and add a single line of text:

mock-maker-inline

After that, mocking the final method should work just fine.

Upvotes: 0

CoolMind
CoolMind

Reputation: 28748

In my case a tested method called another method as a parameter:

Mockito.`when`(repository.getItems(prefs.getUser().id)).thenReturn(listOf())`

While repository is mocked, prefs.getUser().id) will throw NPE. So, first we should mock a parameter, for instance,

Mockito.`when`(prefs.getUser()).thenReturn(User(id = 1, name = "user"))`

Also we should mock prefs. I didn't check it and changed a library, sorry.

Upvotes: 0

Jack
Jack

Reputation: 2223

This is where google took me when I had the same NullPointerException with Junit 5, but was correctly using @ExtendWith(MockitoExtension.class) in my maven project.

Turns out I hadn't included the maven-surefire-plugin in my pom.xml and that meant the @ExtendWith wasn't actually doing anything!

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>2.22.1</version>
    </plugin>
    ...

Upvotes: 1

Omar Ghazi
Omar Ghazi

Reputation: 171

In my case, Intellij created Test with org.junit.jupiter.api.Test (Junit5) instead of import org.junit.Test of (Junit4) which caused all beans to be null apparently. also, make sure the class and test method is public

Upvotes: 2

ives murillo
ives murillo

Reputation: 1

In my case i was missing the annotation @mock in the mapper declaration.

Upvotes: -1

membersound
membersound

Reputation: 86627

In my case, it was the wrong import for when().

I used import static reactor.core.publisher.Mono.when by accident.

Upvotes: 2

Abhishek P
Abhishek P

Reputation: 105

Well in my case it was because of wrong annotation usage. I was using junit 4 for testing and used @BeforeEach instead of @Before while initializing.

Changed it to @Before and it works like charm.

Upvotes: 1

Yogeshwar Bagul
Yogeshwar Bagul

Reputation: 31

For me, it was because I was stubbing the mock in the @BeforeAll method.

MockitoExtension does not have a callback for @BeforeAll.

public class MockitoExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver

I moved the stubbing inside the test method it worked!!

Upvotes: 3

Md. Shahariar Hossen
Md. Shahariar Hossen

Reputation: 1715

Annotate the test class with: @ExtendWith(MockitoExtension.class).

Upvotes: 0

Poulami Pal
Poulami Pal

Reputation: 271

For JUnit 5 the test class has to be annotated with:

@ExtendWith(MockitoExtension.class)

imports:

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

My issue was fixed with this addition.

Upvotes: 7

Satya Samal
Satya Samal

Reputation: 1

In my case it was due to wrong import of the @Test annotation

Make sure you are using the following import

import org.junit.jupiter.api.Test;

Upvotes: 0

garg10may
garg10may

Reputation: 6179

Make sure you initialize your mocks.

JUnit4 use @Before

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
}

JUnit5 use @BeforeEach

@BeforeEach
public void setup() {
    MockitoAnnotations.initMocks(this);
}

For JUnit5 check, you are using proper imports also.

import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)

Upvotes: 16

Onome Sotu
Onome Sotu

Reputation: 676

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

Upvotes: 0

Tal Joffe
Tal Joffe

Reputation: 5828

For future readers, another cause for NPE when using mocks is forgetting to initialize the mocks like so:

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

Also make sure you are using JUnit for all annotations. I once accidently created a test with @Test from testNG so the @Before didn't work with it (in testNG the annotation is @BeforeTest)

Upvotes: 36

يعقوب
يعقوب

Reputation: 1222

you need to initialize MockitoAnnotations.initMocks(this) method has to called to initialize annotated fields.

   @Before public void initMocks() {
       MockitoAnnotations.initMocks(this);
   }

for more details see Doc

Upvotes: 6

azizbekian
azizbekian

Reputation: 62179

None of the above answers helped me. I was struggling to understand why code works in Java but not in Kotlin.

Then I figured it out from this thread.

You have to make class and member functions open, otherwise NPE was being thrown.

After making function open tests started to pass.

You might as well consider using compiler's "all-open" plugin:

Kotlin has classes and their members final by default, which makes it inconvenient to use frameworks and libraries such as Spring AOP that require classes to be open. The all-open compiler plugin adapts Kotlin to the requirements of those frameworks and makes classes annotated with a specific annotation and their members open without the explicit open keyword.

Upvotes: 2

anand krish
anand krish

Reputation: 4415

@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

Upvotes: 1

Ryan Shillington
Ryan Shillington

Reputation: 25088

I had this issue and my problem was that I was calling my method with any() instead of anyInt(). So I had:

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

and I had to change it to:

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

I have no idea why that produced a NullPointerException. Maybe this will help the next poor soul.

Upvotes: 377

smac89
smac89

Reputation: 43068

For me the reason I was getting NPE is that I was using Mockito.any() when mocking primitives. I found that by switching to using the correct variant from mockito gets rid of the errors.

For example, to mock a function that takes a primitive long as parameter, instead of using any(), you should be more specific and replace that with any(Long.class) or Mockito.anyLong().

Hope that helps someone.

Upvotes: 30

mindreader
mindreader

Reputation: 1813

None of these answers worked for me. This answer doesn't solve OP's issue but since this post is the only one that shows up on googling this issue, I'm sharing my answer here.

I came across this issue while writing unit tests for Android. The issue was that the activity that I was testing extended AppCompatActivity instead of Activity. To fix this, I was able to just replace AppCompatActivity with Activity since I didn't really need it. This might not be a viable solution for everyone, but hopefully knowing the root cause will help someone.

Upvotes: 0

Serhii Bohutskyi
Serhii Bohutskyi

Reputation: 2259

In my case, I missed add first

PowerMockito.spy(ClassWhichNeedToBeStaticMocked.class);

so this can be helpful to somebody who see such error

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)

Upvotes: 1

lcn
lcn

Reputation: 2279

Ed Webb's answer helped in my case. And instead, you can also try add

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

if you @RunWith(JUnit4.class).

Upvotes: 0

Related Questions