Java 中删除方法的单元测试?
Unit Test for delete method in Java?
我正在尝试通过单元测试来测试以下方法:
@Override
@Transactional
public void delete(UUID uuid) {
final Company company = companyRepository.findByUuid(uuid)
.orElseThrow(() -> new EntityNotFoundException(COMPANY_NAME));
deletionService.delete(company);
companyRepository.save(company);
}
这里是 DeletionService 实现:
@Override
public void delete(final DeletableEntity deletableEntity) {
deletableEntity.setDeleted(true);
deletableEntity.setDeleteDate(Instant.ofEpochMilli(clock.millis()));
deletableEntity.setDeletedByUserUuid(currentUser.getUuid());
}
我创建了以下测试方法:
@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);
}
调试器命中直到 companyRepository.findByUuid(uuid);
行没有任何问题,但执行该行不会抛出错误。我认为这是由于“Mockito.when(...)”中的条件所致。那么,我应该如何修改此测试以便测试我的 soft delete 方法?
这是我的 Company
实体,它从 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;
}
更新: 这是我编辑的方法的最后状态:
@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());
}
如果你想测试这样的方法,你必须通过两个测试来完成:
- 如果
companyRepository.findByUuid()
returns 任何东西,测试 companyRepository.save()
确实被调用;
- 测试该方法在
companyRepository.findByUuid()
returns 什么都没有时抛出 EntityNotFoundException
。
1. 类似于以下内容:
@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));
}
2. 看起来如下(与您的相似):
@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
是一个 AssertJ 方法 (org.assertj.core.api.Assertions.assertThat
).
我正在尝试通过单元测试来测试以下方法:
@Override
@Transactional
public void delete(UUID uuid) {
final Company company = companyRepository.findByUuid(uuid)
.orElseThrow(() -> new EntityNotFoundException(COMPANY_NAME));
deletionService.delete(company);
companyRepository.save(company);
}
这里是 DeletionService 实现:
@Override
public void delete(final DeletableEntity deletableEntity) {
deletableEntity.setDeleted(true);
deletableEntity.setDeleteDate(Instant.ofEpochMilli(clock.millis()));
deletableEntity.setDeletedByUserUuid(currentUser.getUuid());
}
我创建了以下测试方法:
@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);
}
调试器命中直到 companyRepository.findByUuid(uuid);
行没有任何问题,但执行该行不会抛出错误。我认为这是由于“Mockito.when(...)”中的条件所致。那么,我应该如何修改此测试以便测试我的 soft delete 方法?
这是我的 Company
实体,它从 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;
}
更新: 这是我编辑的方法的最后状态:
@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());
}
如果你想测试这样的方法,你必须通过两个测试来完成:
- 如果
companyRepository.findByUuid()
returns 任何东西,测试companyRepository.save()
确实被调用; - 测试该方法在
companyRepository.findByUuid()
returns 什么都没有时抛出EntityNotFoundException
。
1. 类似于以下内容:
@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));
}
2. 看起来如下(与您的相似):
@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
是一个 AssertJ 方法 (org.assertj.core.api.Assertions.assertThat
).