gpt4 book ai didi

java - 简化和改进数据类型映射器的单元测试

转载 作者:行者123 更新时间:2023-12-01 18:18:02 27 4
gpt4 key购买 nike

我已经使用 Mapstruct 编写了类型映射器,以在实体和 DTO 之间映射时完成一些常见任务,例如重命名属性、通过将它们从嵌套结构移出到根级别来“挑选”它们等。初始 PoC实现如下:

@Mapper(
componentModel = "spring",
injectionStrategy = InjectionStrategy.CONSTRUCTOR,
uses = {DocumentationMapper.class},
imports = {Kind.class})
public interface ConnectorMapper {
@Mapping(source = "metadata.extendedProperties", target = "metadata.additionalProperties")
@Mapping(source = "metadata.documentation", target = "documentation")
@Mapping(source = "metadata.name", target = "name")
@Mapping(source = "spec", target = "connectorSpecYaml")
ConnectorDto fromEntity(final ConnectorYaml connectorYaml);

@InheritInverseConfiguration
@Mapping(target = "kind", expression = "java(Kind.Connector)")
ConnectorYaml fromDto(final ConnectorDto connectorDto);
}

这个映射器基本上执行以下操作:

  1. 将嵌套属性 metadata.extendedProperties 重命名为 metadata.additionalProperties,反之亦然。
  2. 精心挑选 DTO 的嵌套 metadata.documentation 属性,并应用 DocumentationMapper 中定义的映射规则(通过 uses 子句)以及反之亦然。
  3. 优先选择 DTO 的嵌套 metadata.name 属性,反之亦然。
  4. spec 属性重命名为 connectorSpecYaml,反之亦然。

为了对这种行为进行单元测试,我不得不编写一些几乎无法阅读的疯狂断言:

@Test
public void connectorMapperFromEntity() {
// GIVEN a connector entity with fixed values
final var connector = FixtureBuilder.createConnectorYaml("connector");

// WHEN mapping the entity to a DTO
final var connectorDto = connectorMapper.fromEntity(connector);

// THEN the mapping yields a result
assertThat(connectorDto).isNotNull();
// AND the name has been cherry-picked from metadata into the target
assertThat(connectorDto.getName()).isEqualTo(connector.getMetadata().getName());
// AND the metadata has been mapped correctly
assertThat(connectorDto.getMetadata())
.isEqualToIgnoringGivenFields(connector.getMetadata(), "additionalProperties");
// AND the extended properties in metadata have been renamed correctly
assertThat(connectorDto.getMetadata().getAdditionalProperties())
.isEqualTo(connector.getMetadata().getExtendedProperties());
// AND the documentation has been cherry-picked into the target
assertThat(connectorDto.getDocumentation())
.isEqualToIgnoringGivenFields(
connector.getMetadata().getDocumentation(), "additionalProperties");
// AND the extended properties in documentation have been renamed correctly
assertThat(connectorDto.getDocumentation().getAdditionalProperties())
.isEqualTo(connector.getMetadata().getDocumentation().getExtendedProperties());
// AND the spec has been mapped correctly
assertThat(connectorDto.getConnectorSpecYaml()).isEqualTo(connector.getSpec());
}

由于从 fixture 数据手动构建 DTO,另一个方向同样难以阅读:

@Test
public void connectorMapperFromDto() {
final var fixture = FixtureBuilder.createConnectorYaml("connector");
final var connectorDto =
ConnectorDto.builder()
.connectorSpecYaml(fixture.getSpec())
.metadata(
MetadataDto.builder()
.additionalProperties(fixture.getMetadata().getExtendedProperties())
.labels(fixture.getMetadata().getLabels())
.build())
.documentation(
DocumentationDto.builder()
.additionalProperties(
fixture.getMetadata().getDocumentation().getExtendedProperties())
.exampleUsage(fixture.getMetadata().getDocumentation().getExampleUsage())
.longDescription(fixture.getMetadata().getDocumentation().getLongDescription())
.shortDescription(
fixture.getMetadata().getDocumentation().getShortDescription())
.exampleResponse(fixture.getMetadata().getDocumentation().getExampleResponse())
.build())
.name(fixture.getMetadata().getName())
.build();
final var connector = connectorMapper.fromDto(connectorDto);
assertThat(connector).isNotNull();
assertThat(connector).isEqualTo(fixture);
}

此时我很好奇是否有其他方法可以简化测试不执行简单重命名操作的映射器。我正在考虑某种方法来对 JSON 中的输入和预期输出对象进行硬编码,而不是手动构建和比较它们。这是一种可行的方法还是有更合适的方法?

最佳答案

您可以做的就是用随机测试数据填充您的 DTO。检查here这个怎么做。

然后你可以编写一个像这样的测试用例(它有点伪代码,但希望它传达了我的想法):


@Test
public void testNonNullCases() {

ConnectorDto controlDto = generateTestData( ConnectorDto.class );

// map hence-and-forth
ConnectorYaml resultEntity = connectorMapper.fromDto( controlDto );
ConnectorDto resultDto = connectorMapper.fromEntity( resultEntity );

// use assertj to verify them (nested and all)

assertThat( resultDto )
.usingRecursiveComparison()
.ignoringFields( /* fields that you want to do by hand to cover exceptions */
.isEqualTo( controlDto );

// do remaining assertions.

}

@Test
public void testNullCases() {

// I would add a testcase were you leave out attributes (null) and some nested classes in your graph.. just to see whether null cases are handled correctly. You might use jacoco (or other coverage) on the generated code to drive this test

}

public static T generateTestData(Class<T> clz) {
// get inspiration from https://github.com/Blastman/DtoTester/pull/1
}

}

关于java - 简化和改进数据类型映射器的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60329350/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com