package org.testory.plumbing.mock; import static org.testory.plumbing.Mocking.mocking; import static org.testory.plumbing.PlumbingException.check; import static org.testory.plumbing.history.FilteredHistory.filter; import static org.testory.proxy.Typing.subclassing; import org.testory.plumbing.Maker; import org.testory.plumbing.PlumbingException; import org.testory.plumbing.Stubbing; import org.testory.plumbing.history.FilteredHistory; import org.testory.plumbing.history.History; import org.testory.proxy.Handler; import org.testory.proxy.Invocation; import org.testory.proxy.Proxer; public class RawMockMaker implements Maker { private final Proxer proxer; private final History history; private final FilteredHistory<Stubbing> stubbingHistory; private RawMockMaker(Proxer proxer, History history, FilteredHistory<Stubbing> stubbingHistory) { this.proxer = proxer; this.history = history; this.stubbingHistory = stubbingHistory; } public static Maker rawMockMaker(Proxer proxer, History history) { check(proxer != null); check(history != null); FilteredHistory<Stubbing> stubbingHistory = filter(Stubbing.class, history); return new RawMockMaker(proxer, history, stubbingHistory); } public <T> T make(Class<T> type, String name) { check(type != null); check(name != null); Object mock = proxer.proxy(subclassing(type), handler()); history.add(mocking(mock, name)); return (T) mock; } private Handler handler() { return new Handler() { public Object handle(Invocation invocation) throws Throwable { history.add(invocation); Stubbing stubbing = findStubbingFor(invocation); return stubbing.handler.handle(invocation); } }; } public Stubbing findStubbingFor(Invocation invocation) { for (Stubbing stubbing : stubbingHistory.get()) { if (stubbing.invocationMatcher.matches(invocation)) { return stubbing; } } throw new PlumbingException(); } }