sokoler
sokoler

Reputation: 61

WrongTypeOfReturnValue: "Object" cannot be returned by findById()

I am trying to do tests for my Spring boot application, and I've got a big problem. This is how my error looks like:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
WorkItem cannot be returned by findById()
findById() should return Optional

I was following tutorials and everyone is using findOne(), but for me it just doesn't work. My IDE shows:

" Inferred type 'S' for type parameter 'S' is not within its bound; should extend 'com.java.workitemservice.model.WorkItem"

That's why I tried it the other way and used findById(), but then I got another error.

{ 
    @RunWith(SpringRunner.class)  
    @SpringBootTest  
    public class WorkitemServiceApplicationTests {  

    @Mock  
    private WorkItemRepository workItemRepository;

    @InjectMocks
             WorkItemsController workItemsController;

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

    @Test
    public void testGetUserById() {
    WorkItem workItem = new WorkItem();
    workItem.setId(1L);

    //old version
    //when(workItemRepository.findOne(1L)).thenReturn(workItem);
    when(workItemRepository.findById(1L).orElse(null)).thenReturn(workItem);

    WorkItem workItem2 = workItemsController.getWorkItemById(1L);

    verify(workItemRepository).findById(1L).orElse(null);

    assertEquals(1L, workItem2.getId().longValue());
    }
}

My Repository :

    @Repository
    public interface WorkItemRepository extends JpaRepository<WorkItem, 
    Long> {

    Optional <WorkItem> findWorkItemBySubject(String subject);
    }

My service method:

    public WorkItem getWorkItemById(Long id) {
    return this.workItemRepository.findById(id)
    .orElseThrow(() -> new 
    ResourceNotFoundException("WorkItem", "id", id));
    }

My Controller method :

    @GetMapping("/workItems/{id}")
    public WorkItem getWorkItemById(@PathVariable(value = "id") Long 
    workItemId) {

    return this.workItemService.getWorkItemById(workItemId);
    }
}

Upvotes: 4

Views: 2754

Answers (4)

abdella
abdella

Reputation: 754

orElse() method is not part of JPA, but it is method of Optional<T> class as seen from the doc..

To make this clear let's change the following code from the service method

    return this.workItemRepository.findById(id)
    .orElseThrow(() -> new 
    ResourceNotFoundException("WorkItem", "id", id));

to

    Optional<WorkItem> workItem = this.workItemRepository.findById(id);

    return workItem.orElseThrow(() -> new 
             ResourceNotFoundException("WorkItem", "id", id));

So that means orElse method doesn't has to include in the repository method call. Since the orElseThrow method invoked on the Optional workItem, it creates two conditional paths. So for that it needs two test case, test case for exist work item and test case for doesn't exist work item.

Test Case One

  public void testGetWorkItemById_whenWorkItemDoesExist_returnWorkItem() {
        ...
        when(workItemRepository.findById(1L)).thenReturn(Optional.of(workItem));
        ...
        assertEquals(1L, workItem2.getId().longValue());
    }

Test Case Two

   @Test
    public void testGetWorkItemById_whenWorkItemDoesNotExist_returnNull() {
        ...
        when(workItemRepository.findById(1L)).thenReturn(Optional.empty());
        ...
        assertEquals(null, workItem2);
    }

Upvotes: 0

celso
celso

Reputation: 1

Try this:

when(workItemRepository.findById(1L)).thenReturn(Optional.of(Optional.of(workitem).get()));

It woked for me

Upvotes: 0

Mathan
Mathan

Reputation: 7

I see in comments that you tried this :

when(workItemRepository.findById(1L).orElse(null)).thenReturn(Optional.of(workitem));

It should be working. I think the problem is comming from your 'orElse' call.

To be precise, here is the method when :

public static <T> OngoingStubbing<T> when(T methodCall) {
        return MOCKITO_CORE.when(methodCall);
    }

So i think that using 'orElse' prevent 'T' from being inferred.

And my question is why using 'orElse' ? You're stubbing the method.

You can use 'anyString' to match any parameter.

Cheers

Upvotes: 0

Arnaud
Arnaud

Reputation: 17534

As the error states, you are not returning what the method signature declares as a return type (which is Optional<WorkItem>)

Just return

Optional.of(workitem) 

instead of workItem, i.e :

when(workItemRepository.findById(1L).orElse(null)).thenReturn(Optional.of(workitem));

Upvotes: 3

Related Questions