Uploaded image for project: 'Beam'
  1. Beam
  2. BEAM-9000

Java Test Assertions without toString for GenericJson subclasses

    XMLWordPrintableJSON

    Details

    • Type: Improvement
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.19.0
    • Component/s: testing
    • Labels:
      None

      Description

      As of now, there are many tests that assert on toString() of objects.

          CounterUpdate result = testObject.transform(monitoringInfo);
          assertEquals(
              "{cumulative=true, integer={highBits=0, lowBits=0}, "
                  + "nameAndKind={kind=SUM, "
                  + "name=transformedValue-ElementCount}}",
              result.toString());
      

      This style is prone to unnecessary maintenance of the test code when upgrading dependencies. Dependencies may change the internal ordering of fields and trivial change in toString(). In BEAM-8695, where I tried to upgrade google-http-client, there are ~30 comparison failure due to this toString assertions.

      They are subclasses of com.google.api.client.json.GenericJson

      Several options to enhance these assertions.

      Option 1: Assertion using Map

      Leveraging the fact that GenericJson is a subclass of AbstractMap<String, Object>, the assertion can be written as

          ImmutableMap<String, Object> expected = ImmutableMap.of("cumulative", true,
              "integer", ImmutableMap.of("highBits", 0, "lowBits", 0),
              "nameAndKind", ImmutableMap.of("kind", "SUM", "name", "transformedValue-ElementCount"));
      
          assertEquals(expected, (Map<String, Object>)result);
      

      Credit: Ben Whitehead.

      Option 2: Create assertEqualsOnJson

      Leveraging the fact that instance of GenericJson can be instantiated through JSON, the assertion can be written as

          assertEqualsOnJson(
              "{\"cumulative\":true, \"integer\":{\"highBits\":0, \"lowBits\":0}, "
                  + "\"nameAndKind\":{\"kind\":\"SUM\", "
                  + "\"name\":\"transformedValue-ElementCount\"}}",
              result);
      

       

      assertEqualsOnJson is implemented as below. The following field and methods should go to shared test utility class (sdks/testing?)

        private static final JacksonFactory jacksonFactory = JacksonFactory.getDefaultInstance();
      
        public static <T extends GenericJson> void assertEqualsOnJson(String expectedJsonText, T actual) {
          CounterUpdate expected = parse(expectedJsonText, CounterUpdate.class);
          assertEquals(expected, actual);
        }
      
        public static <T extends GenericJson> T parse(String text, Class<T> clazz) {
          try {
            JsonParser parser = jacksonFactory.createJsonParser(text);
            return parser.parse(clazz);
          } catch (IOException ex) {
            throw new IllegalArgumentException("Could not parse the text as " + clazz, ex);
          }
        }
      

      A feature request to handle escaping double quotes via JacksonFactory: https://github.com/googleapis/google-http-java-client/issues/923

       

      Option3: Check JSON equality via JSONassert

      The JSONassert example does not carry quoted double quote characters. The implementation would be converting actual object into JSON object and calling JSONAssert.assertEqual.

      Credit: Luke Cwik

       

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                suztomo Tomo Suzuki
                Reporter:
                suztomo Tomo Suzuki
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 2h
                  2h