How to capture saved value in Java?
Solution 1:
Let's try to break down the functionality of the MenuServiceImpl
's update
method:
public CommandDTO update(final MenuRequest request) {
Menu menu = menuRepository.findByUuid(request.getUuid());
MenuConverter.convert(request, menu); // map fields
Menu saved = menuRepository.save(menu);
return CommandDTO.builder()
.uuid(saved.getUuid())
.build();
}
Here is what this method is doing:
- Fetching existing
Menu
from the repository, finding byuuid
- Converting it i.e. updating it from
request
- Persisting it back in repository using
save
- Creating a
CommandDTO
from saved uuid.
Now, when we write UnitTest for a unit then that means we are testing the working of that unit only.
Here MenuServiceImpl
is not responsible to ensure whether the values were mapped correctly or if the updated value was saved correctly, the only work MenuServiceImpl
performs is to call these dependencies in a particular order and that is all we need to test here.
So, here is a correct test for MenuServiceImpl
's update
method:
@Test
void test_Update() {
MenuRequest request = new MenuRequest("1234");
Menu existingMockMenu = mock(Menu.class);
when(menuRepository.findByUuid("1234")).thenReturn(existingMockMenu);
Menu savedMockMenu = mock(Menu.class);
when(menuRepository.save(existingMockMenu)).thenReturn(savedMockMenu);
menuServiceImpl.update(request);
verify(menuRepository).save(existingMockMenu);
}
If at all you want to test if MenuRepository
is saving the Menu
correctly, you will have to write a new test for MenuRepository
, if this is actually a repository that interacts with the database, then it will be helpful to write DB Integration Test.
Regarding using ArgumentCaptor
, let's suppose your MenuConverter
is changing the values of the menu
, something like this:
public class MenuConverter {
public static void convert(MenuRequest request, Menu menu) {
menu.setName(request.getName() + "_new");
}
}
then first of all, you should have a different test for MenuConverter
that tests this logic, still if you want to test this in the test of MenuServiceImpl
itself, then you don't have to use ArgumentCaptor
, you can use something like:
@Test
void test_Update() {
// same as above
verify(existingMockMenu).setName("Menu1_new");
}
This verifies that MenuConverter
attempted to update the name of your existingMockMenu