Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot pagination - Mockito repository findAll(Pageable) returns null

I am trying to write a simple API to retrieve paged data. My program runs and 'finds all' when not paged. However when I call findAll(Pageable) from the mock repository (Mockito), it returns null.

TaskService.java

import com.example.task.dto.TaskResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface TaskService {
    Page<TaskResponse> findAll(Pageable pageRequest);
}

TaskServiceImpl.java

import com.example.task.domain.TaskEntity;
import com.example.task.dto.TaskResponse;
import com.example.task.repository.TaskRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

public class TaskServiceImpl implements TaskService {
    private TasksRepository tasksRepository;

    public TaskServiceImpl(TasksRepository tasksRepository) {
        this.tasksRepository = tasksRepository;
    }

    @Override
    public Page<TaskResponse> findAll(Pageable pageRequest) {
        Page<TaskEntity> tasks = this.taskRepository.findAll(pageRequest); <=== HERE IT RETURNS NULL

        return tasks;
    }

TaskRepository.java

package com.example.task.repository;

import com.example.task.domain.TaskEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface TaskRepository extends JpaRepository<TaskEntity, Long>, PagingAndSortingRepository<TaskEntity, Long> {
    Page<TaskEntity> findAll(Pageable pageRequest);
}

TaskServiceTest.java

package com.example.task.service;

import com.example.task.domain.TaskEntity;
import com.example.task.repository.TaskRepository;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.*;

class TaskServiceTest {
    private TaskRepository taskRepository = mock(TaskRepository.class);
    private TaskServiceImpl taskService = new TaskServiceImpl(taskRepository);

    @Test
    void FindAll_ReturnsAPagedListOfTasks() {
        when(taskRepository.findAll()).thenReturn(Arrays.asList(
                new TaskEntity(1L, "Fake task 1"),
                new TaskEntity(2L, "Fake task 2"),
                new TaskEntity(3L, "Fake task 3"),
                new TaskEntity(4L, "Fake task 4")
        ));

        Pageable pageRequest = PageRequest.of(0, 4);
        List<TaskResponse> tasks = taskService.findAll(pageRequest).getContent();

        assertThat(tasks.size(), equalTo(4));

        verify(taskRepository).findAll();
    }
}

In TaskServiceImpl.java .findAll(pageRequest) returns null. I am not very familiar with Mockito and wondering if creating a mock repository with it is causing issues? It works just fine when I do .findAll() with no pagination. Is there something wrong with how I am using findAll(Pageable) method from the PagingAndSortingRepository. Thanks!

like image 371
ongelo Avatar asked Apr 01 '19 04:04

ongelo


People also ask

How to use pageable repository in spring data?

In Spring Data, if we need to return a few results from the complete data set, we can use any Pageable repository method, as it will always return a Page. The results will be returned based on the page number, page size, and sorting direction. Spring Data REST automatically recognizes URL parameters like page, size, sort etc.

Why is my pageable mock not working in Mockito?

The problem lies in your test case mock stubbing. You are doing a mix of actual objects and mocked objects which is not a supported functionality in Mockito. You can either use all real objects or all mocked objects. pageable is an actual objects where as the rest of the objects are mocked instances.

What is Spring Boot pagination?

Spring Boot pagination tutorial shows how to paginate data in a Spring application. Spring is a popular Java application framework and Spring Boot is an evolution of Spring that helps create stand-alone, production-grade Spring based applications easily.

How do I get the pageable object in Spring MVC?

In Spring MVC, we can also choose to obtain the Pageable instance in our controller using Spring Data Web Support. Once we have our PageRequest object, we can pass it in while invoking our repository's method: The findAll (Pageable pageable) method by default returns a Page<T> object.


2 Answers

You could solve this by two ways.

Using Mock:

Page<TaskEntity> tasks = Mockito.mock(Page.class);
Mockito.when(this.taskRepository.findAll(org.mockito.Matchers.isA(Pageable.class))).thenReturn(tasks);

Or, Using class instantiation:

List<TaskEntity> tasks = new ArrayList<>();
Page<TaskEntity> pagedTasks = new PageImpl(tasks);
Mockito.when(this.taskRepository.findAll(pagedTasks)).thenReturn(pagedTasks);
like image 196
Mebin Joe Avatar answered Oct 08 '22 22:10

Mebin Joe


You mock a call to the findAll() without parameters and only that will return what you set. To mock a call to the overload that takes a parameter you need to call

when(taskRepository.findAll(org.mockito.Matchers.isA(Pageable.class)).thenReturn(...)

You probably should import org.mockito.Matchers statically to improve readability. You can also use an ArgumentCaptor if you want to verify something about the passed object.

like image 26
Apokralipsa Avatar answered Oct 09 '22 00:10

Apokralipsa