7

I'm attempting to mock an object that returns a Java Optional object with Mockito:

SomeObject someObject = new SomeObject();
Mockito.when(someSpringJpaRepository.findById(Mockito.any(UUID.class))).thenReturn(Optional.of(someObject));

When someSpringJpaRepository.findById(UUID) is called, it returns Optional.empty.

I'm expecting the method findById() to return someObject.
Any reason why it's returning Optional.empty instead?

Here is the method:

public UUID saveOrder(OrderDTO orderDto) {

        Order order = new Order();
        if (orderDto.getId() != null) {
            Optional<Order> result = orderRepository.findById(orderDto.getId());
            if (result != null && result.isPresent()) {
                order = result.get(); // existing record

            } else {
                order.setId(UUID.randomUUID());
            }
        } else {
            // new record
            order.setId(UUID.randomUUID());
        }

        return order.getId();
    }

And here is the Junit:

@Test
    public void saveOrderTest(){

        @Autowired
        private OrderApiService orderApiService;
        @Mock
        private OrderRepository orderRepository;

        OrderDTO orderDto = new OrderDTO();
        UUID orderID = UUID.randomUUID();
        Order order = new Order();
        order.setId(orderID);

        orderDto.setId(orderID);
        Mockito.when(orderRepository.findById(Mockito.any(UUID.class))).thenReturn(Optional.of(order));
        assertNotNull(orderApiService.saveOrder(orderDto));
    }

Amy Bachir
  • 115
  • 2
  • 2
  • 6
  • 1
    Do share the signature of `findById` in the question. If the return type is `Optional` for that method, then your mocking is correct but the expectation is incorrect. If the return type is `T` for the method, then your mocking is incorrect and you might want to change it to `.thenReturn(someObject)`. – Naman Feb 26 '19 at 16:10
  • `findById` is the Spring CrudRepository method. I did not override the behavior of this method in the implementation `someSpringJpaRepository` You can find the documentation here: https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html#findById-ID- – Amy Bachir Feb 26 '19 at 16:15
  • `findById()` returns `Optional`. You suggested that my expectation is, therefore, incorrect. What should be my expectation in this case? Thanks! – Amy Bachir Feb 26 '19 at 16:38
  • If the method returns an `Optional`, the expectation should be that it can return `Optional` in that case. Though if the result is `Optional.empty`, it would still be suspicious to me. – Naman Feb 26 '19 at 17:36
  • Yea, it's definitely sketchy! I'm not new to Junit and Mockito so I don't think I have any problems in the code, although I could have made a careless mistake somewhere in the code due to looking at it for a long time. Any suggestions for debugging it? – Amy Bachir Feb 26 '19 at 17:53
  • Can you show more code? In example how do you call this repository method and how do you set your mock? – ByeBye Feb 26 '19 at 20:34
  • I added some details above! – Amy Bachir Feb 27 '19 at 17:42
  • Change `@Mock` to `@MockBean` – ByeBye Feb 27 '19 at 17:44
  • That's it! `@MockBean` worked! You are Awesome @ByeBye – Amy Bachir Feb 27 '19 at 17:57

2 Answers2

4

Your @Mock in class is doing nothing. You created a separate instance of orderRepository which is not injected into your service class. To inject your mock into context use @MockBean

Difference between @Mock and @MockBean here

ByeBye
  • 6,650
  • 5
  • 30
  • 63
1

you can try to use spy method

Repository spyRepo = Mockito.spy(someSpringJpaRepository);
Mockito.doReturn(Optional.of(someObject)).when(spyRepo).findById(Mockito.any(UUID.class));
swolf
  • 96
  • 6
  • Thanks for the suggestion!, However, switching from mock to spy yielded with the same result, an empty Optional object! – Amy Bachir Feb 26 '19 at 16:39