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!
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.
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.
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.
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.
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With