单元测试的正确方法 CrudRepository.save()

Correct way to unit test CrudRepository.save()

我有一项服务 class,它根据 id, name and money.

查询 CRUDRepository

如果数据存在,它将提取钱,向其添加 100 并将更新后的对象保存在存储库中。 如果数据不存在,它将创建一个新对象并将其保存在存储库中。

Person.java

@Value
@Builder
public class Person {

    private final UUID id;
    private final String name;
    @With
    private final BigDecimal money;
    
}

Service.Java

private Person updateOrSave(final UUID id, final String name) {

        final Optional<Person> existingPerson = myRepo.findByIdAndName(id, name);

        if (existingPerson.isPresent()) {
             updatedPerson = existingPerson.withMoney(existingPerson.getMoney().add(new BigDecimal(100)));
            return myRepo.save(updatedPerson);
        } else {
            return myRepo.save(Person.builder()
                .id(id)
                .name(name)
                .money(money)
                .build()));
        }
    }


我需要为这种存在数据的场景编写单元测试。 我能够编写测试用例,但问题是 myCrudRepository.save() returns null.

这就是我测试它的方式。

Test.java

@ExtendWith(MockitoExtension.class)
class PersonTest {

    @Mock
    private MyRepo myRepo;

    @InjectMocks
    private Service service;
    
    
    
    @Test
    void updateExistingMoney() {

        final UUID id = UUID.randomUUID();
        final String name = "TestName";


        final Optional<Person> person = Optional.of(Person.builder()
                .id(id)
                .name(name)
                .money(new BigDecimal(10))
                .build());

        final Person finalPerson = Person.builder()
                .id(id)
                .name(name)
                .money(new BigDecimal(110))
                .build()

        when(myRepo.findByIdAndName(id, name))
            .thenReturn(person);

        service.updateOrSave(id, name);

        verify(myRepo).save(finalPerson);

    }
    

Is this correct way of testing or is it wrong ?

您可以使用 Argument captors 的概念来捕获作为参数传递给模拟存储库的对象。

@ExtendWith(MockitoExtension.class)
class PersonTest {

    @Mock
    private MyRepo myRepo;

    @InjectMocks
    private Service service;

    @Captor
    private ArgumentCaptor<Person> personCaptor;


    @Test
    void updateExistingMoney() {

        final UUID id = UUID.randomUUID();
        final String name = "TestName";


        final Optional<Person> person = Optional.of(Person.builder()
                .id(id)
                .name(name)
                .money(new BigDecimal(10))
                .build());

        final Person finalPerson = Person.builder()
                .id(id)
                .name(name)
                .money(new BigDecimal(110))
                .build()

        when(myRepo.findByIdAndName(id, name))
                .thenReturn(person);

        service.updateOrSave(id, name);

        verify(myRepo).save(personCaptor.capture());

        final Person actual = personCaptor.getValue();

        // Do checks on expected person vs. the actual one
    }