diff --git a/src/main/java/dev/openfeature/sdk/ImmutableContext.java b/src/main/java/dev/openfeature/sdk/ImmutableContext.java index c8992db18..dd65538b8 100644 --- a/src/main/java/dev/openfeature/sdk/ImmutableContext.java +++ b/src/main/java/dev/openfeature/sdk/ImmutableContext.java @@ -88,6 +88,9 @@ public String getTargetingKey() { @Override public EvaluationContext merge(EvaluationContext overridingContext) { if (overridingContext == null || overridingContext.isEmpty()) { + if (this.isEmpty()) { + return ImmutableContext.EMPTY; + } return new ImmutableContext(this.asUnmodifiableMap()); } if (this.isEmpty()) { diff --git a/src/test/java/dev/openfeature/sdk/ImmutableContextTest.java b/src/test/java/dev/openfeature/sdk/ImmutableContextTest.java index a365b6fc2..08744fc3e 100644 --- a/src/test/java/dev/openfeature/sdk/ImmutableContextTest.java +++ b/src/test/java/dev/openfeature/sdk/ImmutableContextTest.java @@ -253,6 +253,41 @@ void nullTargetingKeyWithNullAttributesYieldsEmptyContext() { } } + @Nested + @DisplayName("ImmutableContext.merge() empty short-circuit") + class MergeEmpty { + + @Test + @DisplayName("merging two empty contexts returns the EMPTY singleton") + void mergingTwoEmptyContextsReturnsEmptySingleton() { + EvaluationContext result = new ImmutableContext().merge(new ImmutableContext()); + assertThat(result).isSameAs(ImmutableContext.EMPTY); + } + + @Test + @DisplayName("merging empty context with null returns the EMPTY singleton") + void mergingEmptyContextWithNullReturnsEmptySingleton() { + EvaluationContext result = new ImmutableContext().merge(null); + assertThat(result).isSameAs(ImmutableContext.EMPTY); + } + + @Test + @DisplayName("merging non-empty context with null does not return EMPTY") + void mergingNonEmptyContextWithNullDoesNotReturnEmpty() { + EvaluationContext result = new ImmutableContext("key").merge(null); + assertThat(result).isNotSameAs(ImmutableContext.EMPTY); + assertThat(result.getTargetingKey()).isEqualTo("key"); + } + + @Test + @DisplayName("merging non-empty context with empty override does not return EMPTY") + void mergingNonEmptyContextWithEmptyOverrideDoesNotReturnEmpty() { + EvaluationContext result = new ImmutableContext("key").merge(new ImmutableContext()); + assertThat(result).isNotSameAs(ImmutableContext.EMPTY); + assertThat(result.getTargetingKey()).isEqualTo("key"); + } + } + @Nested class Equals { ImmutableContext ctx = new ImmutableContext("c", Map.of("a", new Value("b")));