【问题标题】:JUnit Extensions randombeans - exclude property of object within collectionJUnit Extensions randombeans - 排除集合中对象的属性
【发布时间】:2018-03-13 18:42:32
【问题描述】:

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

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

专辑包含List&lt;Image&gt; 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;

第一个图像(索引 0)总是“碰巧”正确生成,但其他图像已排除属性集。

我也在使用:

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);
    }
}

【问题讨论】:

    标签: unit-testing junit junit5 random-beans


    【解决方案1】:

    JUnit Extensions 包含 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&lt;DomainObject&gt; 和两个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 之间的双向关系引起的。每个Image 都包含对其父Album 的引用,这一事实导致RandomBeans 的RandomizationContext.getFieldFullName()Image 中的每个属性派生了不正确的名称。

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

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

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

    目前 RandomBeans(以及因此 RandomBeansExtension)不支持在以下场景中排除嵌套属性:

    • 嵌套属性位于一个包含多个元素的集合中
    • 该集合中的对象包含对包含类的反向引用
    • 不排除反向引用属性

    我认为这里的解决方法是排除 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());
            }
        }
    } 
    

    【讨论】:

    • 回复您对该问题的最新更新;我仍然无法重现您的问题。如果您可以提供MCVE,其中包含重现问题的最少代码,那么我相信我将能够诊断。您能否将问题简化为一对简单的类(AlbumImage)和一个小测试用例,并用这些细节更新您的问题?鉴于 RandomBeans 扩展的默认行为已被证明可以排除嵌套属性(通过我在答案中链接的测试用例),如果没有 MCVE,我将无法诊断您的问题。
    • 使用github.com/adrhc/photos-server.git。在private Album specialAlbum 上使用适当的@Random。在 AlbumPageServiceTest.setUpSpecialAlbum 中为第一行设置一个调试断点,然后开始调试任何测试方法。到达断点时检查 this.specialAlbum 的值。为了使完整的测试能够正常工作,您还必须使用 mysqlexifweb-no-data.sql 脚本,但对于我们的目的而言,调试就足够了。跨度>
    • 我刚刚运行该测试并在AlbumPageServiceTest.setUpSpecialAlbum 的第一行暂停我看到specialAlbum 已被填充,不包括id, dirty, images, cover, lastUpdate,就像该类成员状态上的注释一样。我还不清楚你希望我看到什么。注意:我注释掉了@Junit5PhotosStagingDbConfig,因为我没有时间安装mysql并运行exifweb-no-data.sql ...我认为该测试用例在MCVE中的M上丢失了... “最小 - 使用尽可能少的代码,但仍然会产生同样的问题” :)
    • 如果你能生成一个重现问题的最小示例(4 个类就足够了 - Album、Image、RandomBeansExtensionEx 和一个小测试用例),我会再看看。
    • 显然缺少M 部分:D。请使用@Random(excludes = {"id", "dirty", "cover", "lastUpdate", "images.id", "images.lastUpdate", "images.status", "images.deleted"})private Album specialAlbum上方的第1条注释行)并注释当前使用的@Random(excludes = {"id", "lastUpdate", "status", "deleted"})
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    相关资源
    最近更新 更多