@Test public void testSanity() throws Exception { final AtomicLong numJobsComplete = new AtomicLong(0); /** ** Setup mockFlow1 *** */ final Capture<FlowCallback> flow1Callback = new Capture<FlowCallback>(); mockFlow1.execute(EasyMock.eq(props), EasyMock.capture(flow1Callback)); EasyMock.expectLastCall() .andAnswer( new IAnswer<Void>() { @Override public Void answer() throws Throwable { Assert.assertEquals(Status.RUNNING, flow.getStatus()); Assert.assertEquals(1, numJobsComplete.incrementAndGet()); flow1Callback.getValue().completed(Status.SUCCEEDED); Assert.assertEquals(Status.RUNNING, flow.getStatus()); return null; } }) .once(); Props mockFlow1Props = new Props(); mockFlow1Props.put("1", "1"); mockFlow1Props.put("2", "1"); EasyMock.expect(mockFlow1.getStatus()).andReturn(Status.SUCCEEDED).times(2); EasyMock.expect(mockFlow1.getReturnProps()).andReturn(mockFlow1Props).once(); /** ** Setup mockFlow2 *** */ final Capture<FlowCallback> flow2Callback = new Capture<FlowCallback>(); mockFlow2.execute(EasyMock.eq(props), EasyMock.capture(flow2Callback)); EasyMock.expectLastCall() .andAnswer( new IAnswer<Void>() { @Override public Void answer() throws Throwable { Assert.assertEquals(Status.RUNNING, flow.getStatus()); Assert.assertEquals(2, numJobsComplete.incrementAndGet()); flow2Callback.getValue().completed(Status.SUCCEEDED); Assert.assertEquals(Status.SUCCEEDED, flow.getStatus()); return null; } }) .once(); EasyMock.expect(mockFlow2.getStatus()) .andAnswer( new IAnswer<Status>() { private volatile AtomicInteger count = new AtomicInteger(0); @Override public Status answer() throws Throwable { switch (count.getAndIncrement()) { case 0: return Status.READY; case 1: return Status.SUCCEEDED; default: Assert.fail("mockFlow2.getStatus() should only be called 2 times."); } return null; } }) .times(2); Props mockFlow2Props = new Props(); mockFlow2Props.put("2", "2"); mockFlow2Props.put("3", "2"); EasyMock.expect(mockFlow2.getReturnProps()).andReturn(mockFlow2Props).once(); EasyMock.expect(props.equalsProps(props)).andReturn(true).once(); EasyMock.replay(mockFlow1, mockFlow2, props); /** ** Start the test *** */ AtomicBoolean callbackRan = new AtomicBoolean(false); flow.execute( props, new OneCallFlowCallback(callbackRan) { @Override public void theCallback(Status status) { Assert.assertEquals(Status.SUCCEEDED, status); Assert.assertEquals(2, numJobsComplete.get()); } }); Assert.assertTrue("Callback wasn't run.", callbackRan.get()); Assert.assertEquals(Status.SUCCEEDED, flow.getStatus()); Assert.assertEquals(emptyExceptions, flow.getExceptions()); Assert.assertEquals(props, flow.getParentProps()); callbackRan = new AtomicBoolean(false); flow.execute( props, new OneCallFlowCallback(callbackRan) { @Override protected void theCallback(Status status) { Assert.assertEquals(Status.SUCCEEDED, status); Assert.assertEquals(2, numJobsComplete.get()); } }); Assert.assertTrue("Callback wasn't run.", callbackRan.get()); Assert.assertEquals(Status.SUCCEEDED, flow.getStatus()); Assert.assertEquals(emptyExceptions, flow.getExceptions()); Props retProps = flow.getReturnProps(); Assert.assertEquals(3, retProps.size()); Assert.assertEquals("1", retProps.get("1")); Assert.assertEquals("2", retProps.get("2")); Assert.assertEquals("2", retProps.get("3")); EasyMock.verify(props); EasyMock.reset(props); EasyMock.expect(props.equalsProps(props)).andReturn(false).once(); EasyMock.replay(props); boolean exceptionThrown = false; try { flow.execute( props, new FlowCallback() { @Override public void progressMade() {} @Override public void completed(Status status) {} }); } catch (IllegalArgumentException e) { exceptionThrown = true; } Assert.assertTrue( "Expected an IllegalArgumentException to be thrown because props weren't the same.", exceptionThrown); }