Home > other >  How to capture saved value in Java?
How to capture saved value in Java?

Time:01-16

I am trying to create a unit test for the following 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();
}

I want to capture saved parameter as it is not returned from the method using the following unit test:

@RunWith(MockitoJUnitRunner.class)
public class MenuServiceImplTest {

    @InjectMocks
    private MenuServiceImpl menuService;

    @Captor
    private ArgumentCaptor<Menu> menuCaptor;

    // mocks (code omitted for brevity)

    @Test
    public void test_Update() {

        // ...

        CommandDTO result = menuService.update(request);

        verify(menuRepository).save(menuCaptor.capture());
        final Menu captured = menuCaptor.getValue();
    }
}

However, the parameter in menuRepository.save() is the unsaved parameter, but I need to capture saved parameter. So, how can I do this? Should I use @Spy instead of ArgumentCaptor?

CodePudding user response:

If that is a unit test, then I assume you already mock MenuRepository.

To properly mock MenuRepository, you need to define the behavior of menuRepository.findByUuid(request.getUuid()) and menuRepository.save(menu).

Once you define menuRepository.findByUuid(request.getUuid()), you need to create a Menu instance. All you need to do is, to check if the fields of that menu are updated properly.

CodePudding user response:

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:

  1. Fetching existing Menu from the repository, finding by uuid
  2. Converting it i.e. updating it from request
  3. Persisting it back in repository using save
  4. 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.

  •  Tags:  
  • Related