### Question:
SynchronizedOnIdentifierHandler { public <V> V perform(Callback<V> callback) { notNull(callback); notNull(callback.getIdentifier()); if (obtainLock) { lock.obtainLock(callback.getIdentifier()); } try { return callback.execute(); } catch (Exception e) { throw new InvocationException("Invoke on " + callback.getIdentifier() + " error", e); } finally { if (obtainLock) { lock.releaseLock(callback.getIdentifier()); } } }  V perform(Callback<V> callback);  }### Answer:
@Test public void testPerform() throws Exception { final SynchronizedOnIdentifierHandler handler = new SynchronizedOnIdentifierHandler(); final Boolean performed = handler.perform(new Callback<Boolean>() { @Override public String getIdentifier() { return "1"; } @Override public Boolean execute() throws Exception { return true; } }); assertThat(performed, is(true)); }
@Test(expected = InvocationException.class) public void testPerformException() throws Exception { final SynchronizedOnIdentifierHandler handler = new SynchronizedOnIdentifierHandler(); handler.perform(new Callback<Void>() { @Override public String getIdentifier() { return "1"; } @Override public Void execute() throws Exception { throw new Exception(); } }); }