Chain implements Iterable<T> { @Override public String toString() { StringBuilder b = new StringBuilder(); b.append("chain '").append(id).append("'{"); boolean first = true; for (T component : components) { if (!first) { b.append("->"); } else { first = false; } b.append(" ").append(component.getClass().getSimpleName()).append(" "); } b.append("}"); return b.toString(); } @SafeVarargs  Chain(String id, T... components);  Chain(String id, List<? extends T> components); String id(); boolean isEmpty(); @Override Iterator<T> iterator(); @Override String toString(); @Override int hashCode(); @Override boolean equals(Object other); boolean equals(Chain<?> other);  }
@Test public void empty_chain_toString() { Chain<Filter> c = new Chain<>("myChain"); assertEquals("chain 'myChain'{}", c.toString()); }
@Test public void singleton_chain_toString() { Chain<Filter> c = new Chain<>("myChain", new Filter()); assertEquals("chain 'myChain'{ Filter }", c.toString()); }
@Test public void chain_toString() { Chain<Filter> c = new Chain<>("myChain", new Filter(), new Filter(), new OtherFilter()); assertEquals("chain 'myChain'{ Filter -> Filter -> OtherFilter }", c.toString()); }