it-swarm.com.ru

Mockito - NullpointerException при использовании метода заглушки

Поэтому я начал писать тесты для нашего Java-Spring-проекта. 

Я использую JUnit и Mockito. Говорят, что когда я использую опцию when () ... thenReturn (), я могу имитировать сервисы, не моделируя их или около того. Итак, что я хочу сделать, это установить:

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

Но независимо от того, когда я делаю предложение, я всегда получаю исключение NullpointerException, что, конечно, имеет смысл, потому что input имеет значение null. 

Также, когда я пытаюсь смоделировать другой метод из объекта: 

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

Там я также получаю Nullpointer, потому что методу нужна переменная, которая не установлена. 

Но я хочу использовать 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();
        }   
}

И вот мой тестовый класс:

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


}
27
user5417542

Возвращаемое по умолчанию значение методов, которые вы еще не указали, - 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);

Или же вы можете указать другой ответ по умолчанию при создании макета, чтобы методы возвращали новый макет вместо нуля: RETURNS_DEEP_STUBS

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

Вы должны прочитать Javadoc из Mockito.RETURNS_DEEP_STUBS , который объясняет это более подробно, а также содержит некоторые предупреждения о его использовании.

Надеюсь, это поможет. Просто обратите внимание, что ваш пример кода, кажется, имеет больше проблем, таких как пропущенные операторы assert или verify и вызывающие сеттеры на mocks (что не имеет никакого эффекта).

34
ahu

У меня была эта проблема, и моя проблема заключалась в том, что я вызывал свой метод с any() вместо anyInt(). Итак, у меня было:

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

и мне пришлось изменить его на:

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

Я понятия не имею, почему это вызвало исключение NullPointerException. Может быть, это поможет следующей бедной душе.

68
Ryan Shillington

У меня была та же проблема, и моя проблема была просто в том, что я не правильно аннотировал класс, используя @RunWith. В вашем примере убедитесь, что у вас есть:

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

Как только я это сделал, исключения NullPointerExceptions исчезли.

31
Ed Webb

Для меня причина, по которой я получал NPE, заключается в том, что я использовал Mockito.any(), когда высмеивал примитивы. Я обнаружил, что, переключаясь на использование правильного варианта от mockito, избавляется от ошибок.

Например, чтобы смоделировать функцию, которая принимает примитив long в качестве параметра, вместо использования any(), вам нужно быть более конкретным и заменить его на any(Long.class) или Mockito.anyLong().

Надеюсь, что это помогает кому-то.

4
smac89

Угловой корпус:
Если вы используете Scala и пытаетесь создать сопоставление any в классе value, вы получите бесполезный 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])
   ...
}

Этот другой вопрос SO более конкретно об этом, но вы пропустите его, если не знаете, что проблема связана с классами значений.

3
Vituel

Для будущих читателей другой причиной NPE при использовании mocks является забвение инициализации 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");
   // ...
}
2
Tal Joffe
@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 Аннотация к Context mockContext; 

@Mock 
Context mockContext; 

Но это будет работать, если вы используете @RunWith (MockitoJUnitRunner.class) только. Согласно Mockito вы можете создать фиктивный объект, используя @Mock или Mockito.mock (Context.class);,

Я получил NullpointerException из-за использования @RunWith (PowerMockRunner.class), вместо этого я изменил на @RunWith (MockitoJUnitRunner.class), он работает нормально

1
anand krish

столкнулся с той же проблемой, решение, которое работало для меня:

Вместо того, чтобы издеваться над интерфейсом службы, я использовал @InjectMocks для проверки реализации службы:

@InjectMocks
private exampleServiceImpl exampleServiceMock;

вместо :

@Mock
private exampleService exampleServiceMock;
0
Ajay Vijayasarathy

В моем случае я пропустил сначала добавить 

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)
0
Serhii Bohutskyi

Ни один из этих ответов не работал для меня. Этот ответ не решает проблему OP, но так как этот пост - единственный, который появляется при поиске этой проблемы, я делюсь своим ответом здесь.

Я сталкивался с этой проблемой при написании юнит-тестов для Android. Проблема заключалась в том, что тестируемое действие было расширено AppCompatActivity вместо Activity. Чтобы это исправить, я смог просто заменить AppCompatActivity на Activity, так как он мне действительно не нужен. Это не может быть жизнеспособным решением для всех, но, надеюсь, знание основной причины поможет кому-то. 

0
mindreader

Эд Уэбб ответ помог в моем случае. И вместо этого вы также можете попробовать добавить 

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

если вы @RunWith(JUnit4.class).

0
lcn