【问题标题】:Scan all fields in dtos and find missing and extra fields by their Entities扫描 dtos 中的所有字段并按其实体查找缺失和额外的字段
【发布时间】: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


    【解决方案1】:

    哈哈。我为我的案例找到了解决方案。 我以前的做法是不正确的。因为不可能在每种情况下都按名称正确找到“缺失”和“额外”字段。我决定使用:

    assertThat(entityClass.getDeclaredFields()).hasSameSizeAs(auditDtoClass.getDeclaredFields());
    

    所以这段代码正在检查 entityClass 和 DtoClass 是否声明了相同数量的字段(属性)。如果不是,它会失败测试并打印每个类的所有字段。如果有人有更好的想法,我会很高兴听到。

    【讨论】:

    • 您的答案可以通过其他支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写出好的答案的信息in the help center
    猜你喜欢
    • 2023-01-12
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 2015-07-20
    • 2013-03-24
    • 2019-01-04
    相关资源
    最近更新 更多