Browse Source
Use previous context instead of root for mapping objects within an Inheriting context. This avoids accidental mapping of fields against the root entity after eg. a projection stage. Add missing tests for AggregationOperationRenderer to ensure intended context propagation. Original Pull Request: #44594.0.x
5 changed files with 145 additions and 6 deletions
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
/* |
||||
* Copyright 2023 the original author or authors. |
||||
* |
||||
* 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 |
||||
* |
||||
* https://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 org.springframework.data.mongodb.core.aggregation; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
import static org.mockito.Mockito.*; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.mockito.ArgumentCaptor; |
||||
import org.springframework.data.mongodb.core.aggregation.FieldsExposingAggregationOperation.InheritsFieldsAggregationOperation; |
||||
|
||||
/** |
||||
* @author Christoph Strobl |
||||
*/ |
||||
public class AggregationOperationRendererUnitTests { |
||||
|
||||
@Test // GH-4443
|
||||
void nonFieldsExposingAggregationOperationContinuesWithSameContextForNextStage() { |
||||
|
||||
AggregationOperationContext rootContext = mock(AggregationOperationContext.class); |
||||
AggregationOperation stage1 = mock(AggregationOperation.class); |
||||
AggregationOperation stage2 = mock(AggregationOperation.class); |
||||
|
||||
AggregationOperationRenderer.toDocument(List.of(stage1, stage2), rootContext); |
||||
|
||||
verify(stage1).toPipelineStages(eq(rootContext)); |
||||
verify(stage2).toPipelineStages(eq(rootContext)); |
||||
} |
||||
|
||||
@Test // GH-4443
|
||||
void fieldsExposingAggregationOperationNotExposingFieldsForcesUseOfDefaultContextForNextStage() { |
||||
|
||||
AggregationOperationContext rootContext = mock(AggregationOperationContext.class); |
||||
FieldsExposingAggregationOperation stage1 = mock(FieldsExposingAggregationOperation.class); |
||||
ExposedFields stage1fields = mock(ExposedFields.class); |
||||
AggregationOperation stage2 = mock(AggregationOperation.class); |
||||
|
||||
when(stage1.getFields()).thenReturn(stage1fields); |
||||
when(stage1fields.exposesNoFields()).thenReturn(true); |
||||
|
||||
AggregationOperationRenderer.toDocument(List.of(stage1, stage2), rootContext); |
||||
|
||||
verify(stage1).toPipelineStages(eq(rootContext)); |
||||
verify(stage2).toPipelineStages(eq(AggregationOperationRenderer.DEFAULT_CONTEXT)); |
||||
} |
||||
|
||||
@Test // GH-4443
|
||||
void fieldsExposingAggregationOperationForcesNewContextForNextStage() { |
||||
|
||||
AggregationOperationContext rootContext = mock(AggregationOperationContext.class); |
||||
FieldsExposingAggregationOperation stage1 = mock(FieldsExposingAggregationOperation.class); |
||||
ExposedFields stage1fields = mock(ExposedFields.class); |
||||
AggregationOperation stage2 = mock(AggregationOperation.class); |
||||
|
||||
when(stage1.getFields()).thenReturn(stage1fields); |
||||
when(stage1fields.exposesNoFields()).thenReturn(false); |
||||
|
||||
ArgumentCaptor<AggregationOperationContext> captor = ArgumentCaptor.forClass(AggregationOperationContext.class); |
||||
|
||||
AggregationOperationRenderer.toDocument(List.of(stage1, stage2), rootContext); |
||||
|
||||
verify(stage1).toPipelineStages(eq(rootContext)); |
||||
verify(stage2).toPipelineStages(captor.capture()); |
||||
|
||||
assertThat(captor.getValue()).isInstanceOf(ExposedFieldsAggregationOperationContext.class) |
||||
.isNotInstanceOf(InheritingExposedFieldsAggregationOperationContext.class); |
||||
} |
||||
|
||||
@Test // GH-4443
|
||||
void inheritingFieldsExposingAggregationOperationForcesNewContextForNextStageKeepingReferenceToPreviousContext() { |
||||
|
||||
AggregationOperationContext rootContext = mock(AggregationOperationContext.class); |
||||
InheritsFieldsAggregationOperation stage1 = mock(InheritsFieldsAggregationOperation.class); |
||||
InheritsFieldsAggregationOperation stage2 = mock(InheritsFieldsAggregationOperation.class); |
||||
InheritsFieldsAggregationOperation stage3 = mock(InheritsFieldsAggregationOperation.class); |
||||
|
||||
ExposedFields exposedFields = mock(ExposedFields.class); |
||||
when(exposedFields.exposesNoFields()).thenReturn(false); |
||||
when(stage1.getFields()).thenReturn(exposedFields); |
||||
when(stage2.getFields()).thenReturn(exposedFields); |
||||
when(stage3.getFields()).thenReturn(exposedFields); |
||||
|
||||
ArgumentCaptor<AggregationOperationContext> captor = ArgumentCaptor.forClass(AggregationOperationContext.class); |
||||
|
||||
AggregationOperationRenderer.toDocument(List.of(stage1, stage2, stage3), rootContext); |
||||
|
||||
verify(stage1).toPipelineStages(captor.capture()); |
||||
verify(stage2).toPipelineStages(captor.capture()); |
||||
verify(stage3).toPipelineStages(captor.capture()); |
||||
|
||||
assertThat(captor.getAllValues().get(0)).isEqualTo(rootContext); |
||||
|
||||
assertThat(captor.getAllValues().get(1)) |
||||
.asInstanceOf(InstanceOfAssertFactories.type(InheritingExposedFieldsAggregationOperationContext.class)) |
||||
.extracting("previousContext").isSameAs(captor.getAllValues().get(0)); |
||||
|
||||
assertThat(captor.getAllValues().get(2)) |
||||
.asInstanceOf(InstanceOfAssertFactories.type(InheritingExposedFieldsAggregationOperationContext.class)) |
||||
.extracting("previousContext").isSameAs(captor.getAllValues().get(1)); |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue