### Question:
Interpolator implements Serializable { public String interpolate(String str) { EvaluationContext ctx = CTX.get(); if (ctx == null) { try { ctx = new EvaluationContext(this); CTX.set(ctx); return interpolate(str, ctx); } finally { CTX.remove(); } } else { return interpolate(str, ctx); } } Interpolator(Config config); String interpolate(String str);  }### Answer:
@Test public void testNull() { assertThat(interpolate(null)).isNull(); }
@Test public void testEmptyString() { assertThat(interpolate( "" )).isEqualTo(""); }
@Test public void testSimpleVar() { assertThat(interpolate("${var.one}")).isEqualTo("ONE"); }
@Test public void testMultiVars() { assertThat(interpolate("${var.one}${var.two}")).isEqualTo("ONETWO"); }
@Test public void testMixed() { assertThat(interpolate("cheese${var.one}-${var.two}tacos")).isEqualTo("cheeseONE-TWOtacos"); }
@Test public void testVarWithDefaultNotUsed() { assertThat(interpolate("${var.one:42}")).isEqualTo( "ONE"); }
@Test public void testVarWithDefaultUsed() { assertThat(interpolate("${missing.var:42}")).isEqualTo("42"); }
@Test public void testDeeply() { assertThat(interpolate("${var.four}")).isEqualTo("ONE"); }
@Test public void testSimpleRecursion() { try { interpolate("${var.recurse.1}"); fail( "Should have thrown" ); } catch (IllegalArgumentException e) { } }
@Test public void testDeepRecursion() { try { interpolate("${var.recurse.a}"); fail( "Should have thrown" ); } catch (IllegalArgumentException e) { } }
@Test public void testVarMissingNoDefault() { try { interpolate("${missing.var}"); fail("Should have thrown"); } catch (NoSuchElementException e) { } }