Home > OS >  Unit Test for delete method in Java?
Unit Test for delete method in Java?

Time:11-17

I am trying to test the following method by a Unit Test:

@Override
@Transactional
public void delete(UUID uuid) {
    final Company company = companyRepository.findByUuid(uuid)
            .orElseThrow(() -> new EntityNotFoundException(COMPANY_NAME));

    deletionService.delete(company);
    companyRepository.save(company);
}

Here is the DeletionService implementation:

@Override
public void delete(final DeletableEntity deletableEntity) {
    deletableEntity.setDeleted(true);
    deletableEntity.setDeleteDate(Instant.ofEpochMilli(clock.millis()));
    deletableEntity.setDeletedByUserUuid(currentUser.getUuid());
}

I created the following test method:

@Test(expected = EntityNotFoundException.class)
public void test_Delete() {
    final UUID uuid = UUID.randomUUID();
    final String name = "Company";
    final Company company = new Company(name);

    when(companyRepository.findByUuid(uuid)).thenReturn(Optional.of(company));

    companyService.delete(uuid);

    // I think this returns company instead of EntityNotFoundException 
    // due to the condition in "Mockito.when(...)"
    companyRepository.findByUuid(uuid);
}

The debugger hits until companyRepository.findByUuid(uuid); line without any problem, but executing this line does not throw error. I think this is due to the condition in "Mockito.when(...)". So, how should I modify this test so that I test my soft delete method?

Here is my Company entity that extends from DeletableEntity:

//some annotation here
public class Company extends DeletableEntity  {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "company_gen")
    private long id;

    @Column(nullable = false)
    private String name;

    public Company(@Nonnull String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        return super.equals(other);
    }
}
@MappedSuperclass
public class DeletableEntity extends BaseEntity {

    private boolean deleted;

    private Instant deleteDate;

    private UUID deletedByUserUuid;
}

Update: Here is the last status of my edited methods:

@Test
public void test_Successful_Delete() {
    // Arrange
    final String name = "Company";
    final Company company = new Company(name);

    when(companyRepository.findByUuid(company.getUuid()))
        .thenReturn(Optional.of(company));
    doNothing().when(deletionService).delete(isA(Company.class));
    when(companyRepository.save(isA(Company.class))).thenReturn(company);

    // Act
    companyService.delete(company.getUuid());

    // Assert
    verify(deletionService, times(1)).delete(isA(Company.class));
    verify(companyRepository, times(1)).save(isA(Company.class));
}
@Test(expected = EntityNotFoundException.class)
public void test_Delete_thenThrowException() {
    final String name = "Company";
    final Company company = new Company(name);

    when(companyRepository.findByUuid(company.getUuid())).thenReturn(Optional.empty());

    companyService.delete(company.getUuid());
}

CodePudding user response:

If you want to test such a method you have to do it with two tests:

  1. Test that companyRepository.save() is indeed called if companyRepository.findByUuid() returns anything;
  2. Test that the method throw EntityNotFoundException when companyRepository.findByUuid() returns nothing.

The 1. would be something like the following:

@Test
public void test_Successful_Delete() {
    // Arrange
    final UUID uuid = UUID.randomUUID();
    final String name = "Company";
    final Company company = new Company(name);
    when(companyRepository.findByUuid(uuid)).thenReturn(Optional.of(company));
    when(deletionService.delete(isA(Company.class))).thenReturn(true; // I am assuming deletionService.delete() returns a boolean, if that is not the case you will need to adjust this
    when(companyRepository.save(isA(Company.class))).thenReturn(true; // I am assuming companyRepository.save() returns a boolean, if that is not the case you will need to adjust this

    // Act
    companyService.delete(uuid);

    // Assert
    verify(deletionService, times(1)).delete(isA(Company.class));
    verify(companyRepository, times(1)).save(isA(Company.class));
}

The 2. would look as follows (similar to yours):

@Test
public void test_Unsuccessful_Delete() {
    // Arrange
    final UUID uuid = UUID.randomUUID();
    final String name = "Company";
    final Company company = new Company(name);
    when(companyRepository.findByUuid(uuid)).thenReturn(Optional.empty());

    try {
      // Act
      companyService.delete(uuid);
      Assert.fail("Exception not thrown");
    } catch (EntityNotFoundException e) {
      // Assert
      verify(deletionService, never()).delete(isA(Company.class));
      verify(companyRepository, never()).save(isA(Company.class));
    }
}

P.S.: assertThat is an AssertJ method (org.assertj.core.api.Assertions.assertThat).

  • Related