### Question:
PropertyExpander { public static String expandProperties(String input, Map props) { if (input == null) { return null; } Matcher matcher = EXPANSION_PATTERN.matcher(input); StringBuffer expanded = new StringBuffer(input.length()); while (matcher.find()) { String propName = matcher.group(2); String value = (String) props.get(propName); if (value == null) { value = matcher.group(0); } matcher.appendReplacement(expanded, ""); expanded.append(value); } matcher.appendTail(expanded); return expanded.toString(); } private  PropertyExpander(); static String expandProperties(String input, Map props); static String expandSystemProperties(String input);  }### Answer:
@Test void testExpansion() throws Exception { String expanded = PropertyExpander.expandProperties("String with ${defined.property.one} and ${defined.property.two} and ${defined.property.with.dollar.sign.in.value} and ${undefined.property} and some stuff.", props); assertEquals(expanded, "String with value one and value two and $2 and ${undefined.property} and some stuff.", "Expanded string doesn't match expected"); }