Reputation: 61
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
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
Reputation: 1
Try this:
when(workItemRepository.findById(1L)).thenReturn(Optional.of(Optional.of(workitem).get()));
It woked for me
Upvotes: 0
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
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