Skip to content

Conversation

@Shiyang-Zhao
Copy link

This PR fixes nondeterministic behavior in the following flaky tests:

  • com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_bindsBooleanNonStaticFieldAccessors
  • com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_findEnumWithCustomFields_whenNotPublicFieldsOnly
  • com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_findsAllNonStaticFieldAccessors
  • com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_whenMethodDoesNotExists_doesNotThrowException
  • com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_withMixedAccessors

Description

All five tests flaked due to the nondeterministic ordering of fields and methods returned by Java reflection.
WriteOptions.getAccessorsForClass() constructs its accessor list using reflection, which does not guarantee deterministic ordering, yet the original tests assumed fixed positional order (e.g., index 0 must be "x").


Failure messages:

  1. getAccessorsForClass_bindsBooleanNonStaticFieldAccessors
[ERROR] com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_bindsBooleanNonStaticFieldAccessors -- Time elapsed: 0.223 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <test3> but was: <test1>
    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
    at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
    at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
    at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
    at com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_bindsBooleanNonStaticFieldAccessors(WriteOptionsTest.java:571)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
  1. getAccessorsForClass_findEnumWithCustomFields_whenNotPublicFieldsOnly
[ERROR] com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_findEnumWithCustomFields_whenNotPublicFieldsOnly -- Time elapsed: 0.240 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <isStick> but was: <tire>
    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
    at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
    at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
    at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
    at com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_findEnumWithCustomFields_whenNotPublicFieldsOnly(WriteOptionsTest.java:588)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
  1. getAccessorsForClass_findsAllNonStaticFieldAccessors
[ERROR] com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_findsAllNonStaticFieldAccessors -- Time elapsed: 0.237 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <test3> but was: <test1>
    at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
    at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
    at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:182)
    at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:177)
    at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:1145)
    at com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_findsAllNonStaticFieldAccessors(WriteOptionsTest.java:556)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
  1. getAccessorsForClass_whenMethodDoesNotExists_doesNotThrowException
[ERROR] com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_whenMethodDoesNotExists_doesNotThrowException -- Time elapsed: 0.274 s <<< FAILURE!
org.opentest4j.AssertionFailedError: 
expected: "getTotal"
 but was: "y"
    at com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_whenMethodDoesNotExists_doesNotThrowException(WriteOptionsTest.java:533)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
  1. getAccessorsForClass_withMixedAccessors
[ERROR] com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_withMixedAccessors -- Time elapsed: 0.271 s <<< FAILURE!
org.opentest4j.AssertionFailedError: 
expected: "x"
 but was: "y"
    at com.cedarsoftware.io.WriteOptionsTest.getAccessorsForClass_withMixedAccessors(WriteOptionsTest.java:460)
    at java.base/java.lang.reflect.Method.invoke(Method.java:569)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Proposed Changes

  • Removed index-based assumptions in tests (list.get(0), list.get(1), etc.).
  • Rewrote tests to use deterministic map lookups: Map<String, Accessor> map = accessors.stream().collect(...)
  • Validated accessor properties (name, type, declaring class, visibility) rather than relying on list positions.
  • No production code was changed — test-only modification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant