【发布时间】:2023-01-08 16:35:53
【问题描述】:
我想创建一个单元测试,它将使用反射来查找 dto 中所有缺失的字段,这些字段通过其持久性实体实现 BaseDto。这就是我所做的。
@Slf4j
public class EntityAuditDtoTest {
@Test
public void find_MissingAndExtraFieldsThatUsedInAuditDtosByEntity_ReturnMissingAndExtraFields() throws ClassNotFoundException {
// Arrange
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(AuditEntityType.class));
// Find all classes annotated with @AuditEntityType in the package com.example.dto
Set<BeanDefinition> auditDtoBeans = scanner.findCandidateComponents("com.example.dto");
// Act
for (BeanDefinition auditDtoBean : auditDtoBeans) {
Class<?> auditDtoClass = Class.forName(auditDtoBean.getBeanClassName());
// Make sure the DTO class implements BaseAuditDto
if (!BaseAuditDto.class.isAssignableFrom(auditDtoClass)) {
continue;
}
Class<?> entityClass = getEntityClassForDto(auditDtoClass);
Field[] dtoFields = auditDtoClass.getDeclaredFields();
Field[] entityFields = entityClass.getDeclaredFields();
List<String> missingFields = Arrays.stream(entityFields).map(Field::getName)
.filter(field -> Arrays.stream(dtoFields).noneMatch(f -> f.getName().equals(field))).toList();
if (!missingFields.isEmpty()) {
log.error("Missing fields in DTO class: {} \nfor entity class: {} : {}", auditDtoClass.getName(),
entityClass.getName(), missingFields);
}
List<String> extraFields = Arrays.stream(dtoFields).map(Field::getName)
.filter(field -> Arrays.stream(entityFields).noneMatch(f -> f.getName().equals(field))).toList();
if (!extraFields.isEmpty()) {
log.error("Extra fields in DTO class: {} \nfor entity class: {} : {}", auditDtoClass.getName(),
entityClass.getName(), extraFields);
}
}
}
}
但是问题是dto中可能有一个字段在实体类中,但是测试会认为这是一个缺失的字段。
例如:
Dto类:ContractAudit有customerId字段(customerId)。 ContractEntity 有公共 CustomerEntity 客户。 这是相同的字段。但是当然对于测试它们是不同的。我不明白如何忽略它们。我也不想对过滤器进行硬编码以跳过所有带有“id”前缀的结尾。
@Data
@AuditEntityType("Contract")
public class ContractAudit implements BaseAuditDto {
private Long id;
private String ref;
private String status;
private Long customerId;
}
@Entity
@Table(name = "contract")
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ContractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@ToString.Include
private Long id;
@Column(name = "ref", updatable = true)
@ToString.Include
private String ref;
@Column(name = "status")
@ToString.Include
@Enumerated(value = EnumType.STRING)
private ContractStatusEnum status;
@ManyToOne
@JoinColumn(name = "customer_id")
public CustomerEntity customer;
@Column(name = "deleted")
@ToString.Include
private boolean deleted;
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "contract_id")
private List<ContractDocumentEntity> documents;
}
输出: DTO 类中缺少字段:实体类的 ContractAudit:ContractEntity:[客户,已删除,文档]
DTO 类中的额外字段:实体类的 ContractAudit:ContractEntity:[customerId]
我想要缺少的字段:[已删除,文件]
如果您对如何执行此操作有任何其他想法,我很想听听。我不是要求实施。仅供参考)
【问题讨论】:
标签: java junit reflection