当前位置: 首页 > 知识库问答 >
问题:

扫描dtos中的所有字段,并按其实体查找缺失和多余的字段

南宫俊逸
2023-03-14

我想创建一个单元测试,它将使用反射来查找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类:合同审计有客户ID字段(CusterId)。合同实体有公共客户。这是相同的字段。但是当然对于测试来说,它们是不同的。我不明白如何忽略它们。我也不想硬编码过滤器,跳过所有带有“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:[customer,deleted,documents]

DTO类中的额外字段:实体类的contract audit:contract entity:[customerId]

我希望有缺失的字段:[已删除,文档]

如果你有任何关于如何做到这一点的其他想法,我很想听听。我不要求执行。仅建议)

共有1个答案

越文康
2023-03-14

哈哈。我为我的案例找到了解决方案。我之前的方法不正确。因为不可能为每个案例按名称正确找到“缺失”和“额外”字段。我决定使用:

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

因此,此代码检查entityClass和DtoClass是否声明了相同数量的字段(财产)。如果没有通过测试,则打印每个类的所有字段。如果有人有更好的想法,我很乐意听到。

 类似资料:
  • 给出以下实体: 和存储库: 24.12.2018-Edit:我在一个测试项目中配置了自定义实体查找,得到的结果略有不同。创建和检索所有资源的工作符合预期。但是,访问单个资源会引发上述异常。 详细的堆栈跟踪:

  • 我想通过枚举一组给定类的私有字段来动态创建一个类组合映射。这适用于具有一组独立类的getDeclaredFields()。 但是,如果类包含一个字段,该字段的类型是不可用的类,则调用将失败。有没有办法枚举私有字段,这样我就可以避免这种行为,例如一个接一个地捕捉异常并继续处理其余字段?

  • 我用spring boot starter创建了一个基本的graphql java应用程序,并在使用Hibernate和Jpa的MSSQL数据库上使用graphql spqr库。 我有一个名为“任务”的实体,有5个字段。我有一个简单的Jpa存储库和一个调用“findAllTasks”方法的简单Jpa服务。它工作得很好,但是如果我指定(例如)使用graphiql只查询一个字段,我可以通过SQL日志看

  • 问题内容: 我正在使用NHibernate,并且正在寻找一种解决方案,该解决方案将允许我审核实体中所有字段的更改。我希望能够为每个实体(例如,用户-> UsersHistory)创建一个历史表,该表将具有与用户表相同的结构,并具有其他字段,例如操作类型(更新,删除),进行更改的用户的userid等。不想为每个实体定义此类。我正在寻找类似的东西(即),因为这些条目不属于我的域,仅用于准备对该实体所做

  • 问题是,给定一个具有40亿个唯一整数的输入文件,提供一种算法来生成文件中不包含的整数,假设只有10 MB的内存。 在下面搜索了一些解决方案并发布了代码,其中一个是将整数存储到位向量块中(每个块表示40亿范围内的特定整数范围,块中的每个位表示一个整数),并为每个块使用另一个计数器来计算每个块中的整数数。因此,如果整数的数量小于整数的块容量,则扫描块的位向量以查找缺少的整数。 我对此解决方案的问题是,

  • 情境:很少有应用程序使用Java DTO进行通信。我有一个类,它作为字段持有另一个类,它们持有另一个类(从顶部DTO到下面三个级别)。 字段可以是单个DTO或作为其他类(DTO)的ArrayList(排他)。所有类都是DTO。只有私有字段和公共setter和getter。 现在,当我得到top DTO时,有没有办法检查它并获得所有getter,包括嵌套的getter,通过getter,读取字段,然

  • 我在其中一个项目中使用Apache Batik将SVG转换为PDF。该项目是在Tomcat7中运行的Spring应用程序。在Ubuntu下运行的开发机器上一切正常,Tomcat使用$CATALINA_HOME/bin/startup启动。但是当我尝试在CentOS 6的生产服务器上运行应用程序,Tomcat使用命令启动时,应用程序在转换时陷入无限循环。我试着调试这个问题,发现了以下代码: 在类中。

  • 问题内容: 有没有一种方法可以写一个sql查询来查找所有行,其中字段值是给定字符串的子字符串。 例子: 查询应该是这样的 这怎么可能? 如果不可能的话,那么我将不得不在Java中实现该行为。我正在使用jdbc:mysql驱动程序连接到数据库。 更新 您的解决方案工作 现在有点曲折。如果我们要检查字段的子字符串是否作为我们指定的字符串的子字符串出现。 问题答案: 如果在文本中找到之一或必须使用 没有