Back to Repositories

Validating JsonObject Map Interface Implementation in google/gson

This test suite validates the Map interface implementation for JsonObject in the GSON library, ensuring proper JSON object to Map conversion and manipulation capabilities.

Test Coverage Overview

The test suite provides comprehensive coverage of Map interface operations on JsonObject instances.

  • Tests basic Map operations: size, containsKey, containsValue, get, put, remove
  • Validates collection views: keySet, values, entrySet
  • Verifies bidirectional updates between JsonObject and Map view
  • Tests edge cases including null handling and invalid operations

Implementation Analysis

The testing approach uses JUnit to systematically verify the Map interface contract.

Implements thorough assertion chains using Google Truth framework for enhanced readability and precise error messages. Employs patterns like setup-execute-verify and focuses on both positive and negative test cases.

Technical Details

  • Testing Framework: JUnit 4
  • Assertion Libraries: Google Truth, JUnit Assert
  • Key Classes: JsonObject, JsonElement, JsonPrimitive
  • Helper Utilities: MoreAsserts for equals/hashCode testing

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through comprehensive coverage and robust validation.

  • Systematic testing of interface contract compliance
  • Clear test method naming and organization
  • Thorough validation of error conditions and edge cases
  • Consistent assertion patterns and error message formatting

google/gson

gson/src/test/java/com/google/gson/JsonObjectAsMapTest.java

            
/*
 * Copyright (C) 2022 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.gson;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.gson.common.MoreAsserts;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.Test;

/** Tests for {@link JsonObject#asMap()}. */
public class JsonObjectAsMapTest {
  @Test
  public void testSize() {
    JsonObject o = new JsonObject();
    assertThat(o.asMap().size()).isEqualTo(0);

    o.addProperty("a", 1);
    Map<String, JsonElement> map = o.asMap();
    assertThat(map).hasSize(1);

    map.clear();
    assertThat(map).hasSize(0);
    assertThat(o.size()).isEqualTo(0);
  }

  @Test
  public void testContainsKey() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);

    Map<String, JsonElement> map = o.asMap();
    assertThat(map.containsKey("a")).isTrue();
    assertThat(map.containsKey("b")).isFalse();
    assertThat(map.containsKey(null)).isFalse();
  }

  @Test
  public void testContainsValue() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);
    o.add("b", JsonNull.INSTANCE);

    Map<String, JsonElement> map = o.asMap();
    assertThat(map.containsValue(new JsonPrimitive(1))).isTrue();
    assertThat(map.containsValue(new JsonPrimitive(2))).isFalse();
    assertThat(map.containsValue(null)).isFalse();

    @SuppressWarnings({"unlikely-arg-type", "CollectionIncompatibleType"})
    boolean containsInt = map.containsValue(1); // should only contain JsonPrimitive(1)
    assertThat(containsInt).isFalse();
  }

  @Test
  public void testGet() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);

    Map<String, JsonElement> map = o.asMap();
    assertThat(map.get("a")).isEqualTo(new JsonPrimitive(1));
    assertThat(map.get("b")).isNull();
    assertThat(map.get(null)).isNull();
  }

  @Test
  public void testPut() {
    JsonObject o = new JsonObject();
    Map<String, JsonElement> map = o.asMap();

    assertThat(map.put("a", new JsonPrimitive(1))).isNull();
    assertThat(map.get("a")).isEqualTo(new JsonPrimitive(1));

    JsonElement old = map.put("a", new JsonPrimitive(2));
    assertThat(old).isEqualTo(new JsonPrimitive(1));
    assertThat(map).hasSize(1);
    assertThat(map.get("a")).isEqualTo(new JsonPrimitive(2));
    assertThat(o.get("a")).isEqualTo(new JsonPrimitive(2));

    assertThat(map.put("b", JsonNull.INSTANCE)).isNull();
    assertThat(map.get("b")).isEqualTo(JsonNull.INSTANCE);

    var e = assertThrows(NullPointerException.class, () -> map.put(null, new JsonPrimitive(1)));
    assertThat(e).hasMessageThat().isEqualTo("key == null");

    e = assertThrows(NullPointerException.class, () -> map.put("a", null));
    assertThat(e).hasMessageThat().isEqualTo("value == null");
  }

  @Test
  public void testRemove() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);

    Map<String, JsonElement> map = o.asMap();
    assertThat(map.remove("b")).isNull();
    assertThat(map).hasSize(1);

    JsonElement old = map.remove("a");
    assertThat(old).isEqualTo(new JsonPrimitive(1));
    assertThat(map).hasSize(0);

    assertThat(map.remove("a")).isNull();
    assertThat(map).hasSize(0);
    assertThat(o.size()).isEqualTo(0);

    assertThat(map.remove(null)).isNull();
  }

  @Test
  public void testPutAll() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);

    Map<String, JsonElement> otherMap = new HashMap<>();
    otherMap.put("a", new JsonPrimitive(2));
    otherMap.put("b", new JsonPrimitive(3));

    Map<String, JsonElement> map = o.asMap();
    map.putAll(otherMap);
    assertThat(map).hasSize(2);
    assertThat(map.get("a")).isEqualTo(new JsonPrimitive(2));
    assertThat(map.get("b")).isEqualTo(new JsonPrimitive(3));

    var e =
        assertThrows(
            NullPointerException.class,
            () -> map.putAll(Collections.singletonMap(null, new JsonPrimitive(1))));
    assertThat(e).hasMessageThat().isEqualTo("key == null");

    e =
        assertThrows(
            NullPointerException.class, () -> map.putAll(Collections.singletonMap("a", null)));
    assertThat(e).hasMessageThat().isEqualTo("value == null");
  }

  @Test
  public void testClear() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);

    Map<String, JsonElement> map = o.asMap();
    map.clear();
    assertThat(map).hasSize(0);
    assertThat(o.size()).isEqualTo(0);
  }

  @Test
  public void testKeySet() {
    JsonObject o = new JsonObject();
    o.addProperty("b", 1);
    o.addProperty("a", 2);

    Map<String, JsonElement> map = o.asMap();
    Set<String> keySet = map.keySet();
    // Should contain keys in same order
    assertThat(keySet).containsExactly("b", "a").inOrder();

    // Key set doesn't support insertions
    assertThrows(UnsupportedOperationException.class, () -> keySet.add("c"));

    assertThat(keySet.remove("a")).isTrue();
    assertThat(map.keySet()).isEqualTo(Collections.singleton("b"));
    assertThat(o.keySet()).isEqualTo(Collections.singleton("b"));
  }

  @Test
  public void testValues() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 2);
    o.addProperty("b", 1);

    Map<String, JsonElement> map = o.asMap();
    Collection<JsonElement> values = map.values();
    // Should contain values in same order
    assertThat(values).containsExactly(new JsonPrimitive(2), new JsonPrimitive(1)).inOrder();

    // Values collection doesn't support insertions
    assertThrows(UnsupportedOperationException.class, () -> values.add(new JsonPrimitive(3)));

    assertThat(values.remove(new JsonPrimitive(2))).isTrue();
    assertThat(new ArrayList<>(map.values()))
        .isEqualTo(Collections.singletonList(new JsonPrimitive(1)));
    assertThat(o.size()).isEqualTo(1);
    assertThat(o.get("b")).isEqualTo(new JsonPrimitive(1));
  }

  @Test
  public void testEntrySet() {
    JsonObject o = new JsonObject();
    o.addProperty("b", 2);
    o.addProperty("a", 1);

    Map<String, JsonElement> map = o.asMap();
    Set<Entry<String, JsonElement>> entrySet = map.entrySet();

    List<Entry<?, ?>> expectedEntrySet =
        Arrays.asList(
            new SimpleEntry<>("b", new JsonPrimitive(2)),
            new SimpleEntry<>("a", new JsonPrimitive(1)));
    // Should contain entries in same order
    assertThat(new ArrayList<>(entrySet)).isEqualTo(expectedEntrySet);

    // Entry set doesn't support insertions
    assertThrows(
        UnsupportedOperationException.class,
        () -> entrySet.add(new SimpleEntry<>("c", new JsonPrimitive(3))));

    assertThat(entrySet.remove(new SimpleEntry<>("a", new JsonPrimitive(1)))).isTrue();
    assertThat(map.entrySet())
        .isEqualTo(Collections.singleton(new SimpleEntry<>("b", new JsonPrimitive(2))));
    assertThat(o.entrySet())
        .isEqualTo(Collections.singleton(new SimpleEntry<>("b", new JsonPrimitive(2))));

    // Should return false because entry has already been removed
    assertThat(entrySet.remove(new SimpleEntry<>("a", new JsonPrimitive(1)))).isFalse();

    Entry<String, JsonElement> entry = entrySet.iterator().next();
    JsonElement old = entry.setValue(new JsonPrimitive(3));
    assertThat(old).isEqualTo(new JsonPrimitive(2));
    assertThat(map.entrySet())
        .isEqualTo(Collections.singleton(new SimpleEntry<>("b", new JsonPrimitive(3))));
    assertThat(o.entrySet())
        .isEqualTo(Collections.singleton(new SimpleEntry<>("b", new JsonPrimitive(3))));

    var e = assertThrows(NullPointerException.class, () -> entry.setValue(null));
    assertThat(e).hasMessageThat().isEqualTo("value == null");
  }

  @Test
  public void testEqualsHashCode() {
    JsonObject o = new JsonObject();
    o.addProperty("a", 1);

    Map<String, JsonElement> map = o.asMap();
    MoreAsserts.assertEqualsAndHashCode(map, Collections.singletonMap("a", new JsonPrimitive(1)));
    assertThat(map.equals(Collections.emptyMap())).isFalse();
    assertThat(map.equals(Collections.singletonMap("a", new JsonPrimitive(2)))).isFalse();
  }

  /** Verify that {@code JsonObject} updates are visible to view and vice versa */
  @Test
  public void testViewUpdates() {
    JsonObject o = new JsonObject();
    Map<String, JsonElement> map = o.asMap();

    o.addProperty("a", 1);
    assertThat(map).hasSize(1);
    assertThat(map.get("a")).isEqualTo(new JsonPrimitive(1));

    map.put("b", new JsonPrimitive(2));
    assertThat(o.size()).isEqualTo(2);
    assertThat(map.get("b")).isEqualTo(new JsonPrimitive(2));
  }
}