### Question:
AvgExpression extends AbstractAggregationFunction { @Override public ExpressionResult apply(ExpressionContext expressionContext, ExpressionResult input) { ExpressionContext scopedContext = expressionContext.scoped(this); ExpressionResult result = expression.apply(scopedContext, input); AtomicReference<AvgValue> initialSum = scopedContext.computeIfAbsent(alias, () -> new AtomicReference<>(new AvgValue())); if (result == null || !result.isNumeric() || result.getValue() == null) { return new NumericExpressionResult(initialSum.get().getAverage()); } AvgValue newAvg = initialSum.accumulateAndGet(new AvgValue(1, result.getNumericValue()), AvgValue::add); return new NumericExpressionResult(newAvg.getAverage()); } AvgExpression(String alias, Expression expression); @Override ExpressionResult apply(ExpressionContext expressionContext, ExpressionResult input);  }### Answer:
@Test public void testNoValueAvailableLeavesEmptyAverage() { ExpressionResult actual = testSubject.apply(expressionContext, emptyMapValue()); assertTrue(actual.isNumeric()); assertNull(actual.getValue()); }
@Test public void testAdditionalValuesModifyAverage() { ExpressionResult actual1 = testSubject.apply(expressionContext, mapValue("value", numericValue(1L))); ExpressionResult actual2 = testSubject.apply(expressionContext, mapValue("value", numericValue(2L))); ExpressionResult actual3 = testSubject.apply(expressionContext, mapValue("value", numericValue(6L))); assertEquals(BigDecimal.ONE, actual1.getNumericValue()); assertEquals(BigDecimal.valueOf(15, 1), actual2.getNumericValue()); assertEquals(BigDecimal.valueOf(3).toPlainString(), actual3.getNumericValue().toPlainString()); }
@Test public void testNonNumericValuesKeepExistingAverage() { ExpressionResult actual1 = testSubject.apply(expressionContext, mapValue("value", numericValue(1L))); ExpressionResult actual2 = testSubject.apply(expressionContext, mapValue("value", stringValue("string"))); ExpressionResult actual3 = testSubject.apply(expressionContext, mapValue("value", numericValue(19L))); assertEquals(BigDecimal.ONE, actual1.getNumericValue()); assertEquals(BigDecimal.ONE, actual2.getNumericValue()); assertEquals(BigDecimal.TEN.toPlainString(), actual3.getNumericValue().toPlainString()); }
@Test public void testNullValuesKeepExistingAverage() { ExpressionResult actual1 = testSubject.apply(expressionContext, mapValue("value", numericValue(1L))); ExpressionResult actual2 = testSubject.apply(expressionContext, mapValue("value", nullValue())); ExpressionResult actual3 = testSubject.apply(expressionContext, mapValue("value", numericValue(19L))); assertEquals(BigDecimal.ONE, actual1.getNumericValue()); assertEquals(BigDecimal.ONE, actual2.getNumericValue()); assertEquals(BigDecimal.TEN.toPlainString(), actual3.getNumericValue().toPlainString()); }