Requirement { public void setRequiredBy(Requirement<T> req) { req.setRequires(this); } Requirement(T data); T getData(); void setRequires(Requirement<T> req); void setRequiredBy(Requirement<T> req); boolean requires(Requirement<T> req); boolean requiredBy(Requirement<T> req); Collection<Requirement<T>> listRequirements(); @Override String toString(); @Override int hashCode(); @Override boolean equals(Object obj); String toStringWithReqs();  }
@Test public void testCycles() { Requirement parent = new Requirement("parent"); Requirement child1 = new Requirement("child1"); Requirement child3 = new Requirement("child3"); parent.setRequiredBy(child1); child1.setRequiredBy(child3); thrown.expect(RuntimeException.class); thrown.expectMessage("Requirement cycle detected"); child3.setRequiredBy(parent); }
@Test public void testSelfCycles2() { Requirement self = new Requirement(null); thrown.expect(RuntimeException.class); thrown.expectMessage("Requirement cycle detected"); self.setRequiredBy(self); }