Skip to content

Field existence check for the elements of a collection field #3349

@yfei-z

Description

@yfei-z

Describe the bug
It will report "fields don't exist" if trying to specify the compared fields for the elements of a collection field.

  • assertj core version: 3.25.2
  • java version: 17
  • test framework version: JUnit 5

Test case reproducing the bug

	@Data
	static class Person {
		private final String name, address;
		private List<Person> friends = new ArrayList<>(), enemies = new ArrayList<>();
	}

	@Test
	void listElementFieldComparison() {
		Person sherlock1 = new Person("Sherlock Holmes", null);
		sherlock1.friends.add(new Person("Dr. John Watson", null));
		Person sherlock2 = new Person("Sherlock Holmes", null);
		sherlock2.friends.add(new Person("Dr. John Watson", "Baker Street"));

		assertThat(sherlock1).usingRecursiveComparison(RecursiveComparisonConfiguration.builder()
				.withComparedFields("friends.name")
				.build()).isEqualTo(sherlock2);
	}

The outcome

java.lang.IllegalArgumentException: The following fields don't exist: {name in <friends.name>}

	at org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration.checkComparedFieldsExist(RecursiveComparisonConfiguration.java:1092)
	at org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator$ComparisonState.initDualValuesToCompare(RecursiveComparisonDifferenceCalculator.java:146)
	at org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator$ComparisonState.access$100(RecursiveComparisonDifferenceCalculator.java:73)
	at org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator.determineDifferences(RecursiveComparisonDifferenceCalculator.java:237)
	at org.assertj.core.api.recursive.comparison.RecursiveComparisonDifferenceCalculator.determineDifferences(RecursiveComparisonDifferenceCalculator.java:228)
	at org.assertj.core.api.RecursiveComparisonAssert.determineDifferencesWith(RecursiveComparisonAssert.java:1770)
	at org.assertj.core.api.RecursiveComparisonAssert.isEqualTo(RecursiveComparisonAssert.java:157)

Since I only use ComparingProperties as the RecursiveComparisonIntrospectionStrategy, so here is my temporary solution.

public class ComparingProperties extends org.assertj.core.api.recursive.comparison.ComparingProperties {

	@Override
	public Set<String> getChildrenNodeNamesOf(Object node) {
		if (node instanceof Collection<?> c) {
			Iterator<?> i = c.iterator(); if (!i.hasNext()) return Collections.emptySet();
			return getChildrenNodeNamesOf(i.next());
		}
		return super.getChildrenNodeNamesOf(node);
	}

	@Override
	public Object getChildNodeValue(String childNodeName, Object instance) {
		if (instance instanceof Collection<?> c) {
			Iterator<?> i = c.iterator(); if (!i.hasNext()) return null;
			return getChildNodeValue(childNodeName, i.next());
		}
		Object v = super.getChildNodeValue(childNodeName, instance);
		if (v instanceof Collection<?> c && c.isEmpty()) return null;
		return v;
	}
}

Metadata

Metadata

Labels

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions