I have a service class which queries the CRUDRepository based on id, name and money.
If data exists, it will extract the money, add 100 to it and save the updated object in the repository.
If data does not exist, it will create a new object and save it in the repository.
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()));
}
}
I need to write a unit test for this scenario where data exists.
I am able to write the testcase but the issue is myCrudRepository.save() returns null.
So this is how I am testing it.
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 ?
>Solution :
You can use the concept of Argument captors to capture the object, which was passed as an argument to the mocked repo.
@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
}