JUnit 扩展 randombeans - 在集合中排除 属性 个对象

JUnit Extensions randombeans - exclude property of object within collection

我正在使用 junit-extensions/randomBeans,我使用的是这样的东西:

@Random(type = Album.class, excludes = {"images.id", "images.lastUpdate"})
private List<Album> albums;

相册包含 List<Image> images,我试图从随机生成中排除 Image.idImage.lastUpdate,但它不起作用。

我也试过 excludes = {"images[].id", "images[].lastUpdate"} 但还是不行。

知道如何从随机生成中排除图像的 idlastUpdate 吗?

编辑

与以下:

@Random(excludes = {"id", "dirty", "cover", "lastUpdate", "images.id",
            "images.lastUpdate", "images.status", "images.deleted"})
private Album specialAlbum;

第 1 个图像(索引 0)始终 "happens" 正确生成,但其他图像已排除属性集。

我也在用:

public class RandomBeansExtensionEx extends RandomBeansExtension
        implements IEnhancedRandom {
    public RandomBeansExtensionEx() throws IllegalAccessException {
        super();
        FieldUtils.writeField(this, "random",
                EnhancedRandomBuilder.aNewEnhancedRandomBuilder()
        .objectPoolSize(100)
        .overrideDefaultInitialization(true)
        .charset(forName("UTF-8"))
        .randomize(Integer.class, (Supplier<Integer>) () ->
                ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE))
        .randomize(Long.class, (Supplier<Long>) () ->
                ThreadLocalRandom.current().nextLong(0, Long.MAX_VALUE))
        .stringLengthRange(3, 15)
        .collectionSizeRange(1, 50)
        .scanClasspathForConcreteTypes(true)
        .build(), true);
    }
}

JUnit 扩展包含 a test case,它验证嵌套属性的排除:

  @Test
  public void canInjectRandomPartiallyPopulatedDomainObjects(
      @Random(size = 2, type = DomainObject.class, excludes = {"wotsits", "id", "nestedDomainObject.address"})
          List<DomainObject> anyPartiallyPopulatedDomainObjects) {
    assertThat(anyPartiallyPopulatedDomainObjects, notNullValue());
    assertThat(anyPartiallyPopulatedDomainObjects.size(), is(2));
    anyPartiallyPopulatedDomainObjects.forEach(AssertionUtil::assertThatDomainObjectIsPartiallyPopulated);
  }

在此测试用例中,RandomBeans 扩展提供了一个 List<DomainObject> 和两个 DomainObject 实例,每个实例都具有以下特征:

  • wotsits 集合被排除在外,即 null
  • 排除了 id 属性,即 0L 因为这是 long
  • 的默认值
  • 每个nestedDomainObjectaddress属性是null

这表明排除嵌套对象的属性是使用点符号的问题(nestedDomainObject.address

更新:使用您GitHub repo中的代码我创建了以下最小复制案例:

@ExtendWith(RandomBeansExtensionEx.class)
public class NestedAttributeTest {

    @Random(excludes = {"id", "dirty", "cover", "lastUpdate", "images.id", "images.lastUpdate", "images.status", "images.deleted"})
    private Album specialAlbum;

    @Test
    void testAttributeExclusion() {
        assertThat(specialAlbum.getId(), nullValue());
        assertThat(specialAlbum.getCover(), nullValue());
        assertThat(specialAlbum.getLastUpdate(), nullValue());
        assertThat(specialAlbum.getImages(), notNullValue());
        for (Image image : specialAlbum.getImages()) {
            assertThat(image.getId(), nullValue());
            assertThat(image.getLastUpdate(), nullValue());
        }
    }
}

此测试用例失败,从而重现了您的问题。

通过这个复现案例,我可以看出影响您的问题是由 AlbumImage 之间的 bi-directional 关系引起的。事实上,每个 Image 都包含对其父 Album 的引用,导致 RandomBeans 的 RandomizationContext.getFieldFullName()Image 中的每个属性派生出不正确的名称。

  1. 在第一次迭代中,它确定注入图像中的 id 字段名为 image.id,因此它成功排除了它。
  2. 在第二次迭代中,它确定注入图像中的 id 字段名为 images.album.images.id,因此它不会排除它,因为该名称不在 'excludes list'
  3. 在第三次迭代中,它确定注入图像中的 id 字段名为 images.album.images.album.images.id,因此它不会排除它,因为该名称不在 'excludes list' 中 等等

您可以通过...验证这一点

  • 评论 Image.album 并重新 运行 我提供的最小测试,您会看到它通过了。
  • 将配置更改为 .collectionSizeRange(1, 1),这样每个随机集合只有一个元素,您会看到我提供的最小测试通过了。

就目前的情况而言,RandomBeans(以及 RandomBeansExtension)在以下情况下不支持排除嵌套属性:

  • 嵌套属性在一个元素超过 1 个的集合中
  • 该集合中的对象包含对包含 class
  • 的反向引用
  • 不排除后向引用属性

我认为这里的解决方法是排除 item.album 属性。以下测试通过:

@ExtendWith(RandomBeansExtensionEx.class)
public class NestedAttributeTest {

    @Random(excludes = {"id", "dirty", "cover", "lastUpdate", "images.album", "images.id", "images.lastUpdate", "images.status", "images.deleted"})
    private Album specialAlbum;

    @Test
    void testAttributeExclusion() {
        assertThat(specialAlbum.getId(), nullValue());
        assertThat(specialAlbum.getCover(), nullValue());
        assertThat(specialAlbum.getLastUpdate(), nullValue());
        assertThat(specialAlbum.getImages(), notNullValue());
        for (Image image : specialAlbum.getImages()) {
            assertThat(image.getId(), nullValue());
            assertThat(image.getLastUpdate(), nullValue());
        }
    }
}