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.id
和 Image.lastUpdate
,但它不起作用。
我也试过 excludes = {"images[].id", "images[].lastUpdate"}
但还是不行。
知道如何从随机生成中排除图像的 id
和 lastUpdate
吗?
编辑
与以下:
@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
的默认值
- 每个
nestedDomainObject
的address
属性是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());
}
}
}
此测试用例失败,从而重现了您的问题。
通过这个复现案例,我可以看出影响您的问题是由 Album
和 Image
之间的 bi-directional 关系引起的。事实上,每个 Image
都包含对其父 Album
的引用,导致 RandomBeans 的 RandomizationContext.getFieldFullName()
为 Image
中的每个属性派生出不正确的名称。
- 在第一次迭代中,它确定注入图像中的
id
字段名为 image.id
,因此它成功排除了它。
- 在第二次迭代中,它确定注入图像中的
id
字段名为 images.album.images.id
,因此它不会排除它,因为该名称不在 'excludes list'
- 在第三次迭代中,它确定注入图像中的
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());
}
}
}
我正在使用 junit-extensions/randomBeans,我使用的是这样的东西:
@Random(type = Album.class, excludes = {"images.id", "images.lastUpdate"})
private List<Album> albums;
相册包含 List<Image> images
,我试图从随机生成中排除 Image.id
和 Image.lastUpdate
,但它不起作用。
我也试过 excludes = {"images[].id", "images[].lastUpdate"}
但还是不行。
知道如何从随机生成中排除图像的 id
和 lastUpdate
吗?
编辑
与以下:
@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
的默认值
- 每个
nestedDomainObject
的address
属性是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());
}
}
}
此测试用例失败,从而重现了您的问题。
通过这个复现案例,我可以看出影响您的问题是由 Album
和 Image
之间的 bi-directional 关系引起的。事实上,每个 Image
都包含对其父 Album
的引用,导致 RandomBeans 的 RandomizationContext.getFieldFullName()
为 Image
中的每个属性派生出不正确的名称。
- 在第一次迭代中,它确定注入图像中的
id
字段名为image.id
,因此它成功排除了它。 - 在第二次迭代中,它确定注入图像中的
id
字段名为images.album.images.id
,因此它不会排除它,因为该名称不在 'excludes list' - 在第三次迭代中,它确定注入图像中的
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());
}
}
}