2525import java .util .List ;
2626import java .util .concurrent .ExecutorService ;
2727import java .util .concurrent .Executors ;
28+ import java .util .concurrent .Semaphore ;
2829import java .util .concurrent .atomic .AtomicBoolean ;
2930import org .junit .After ;
3031import org .junit .Before ;
3132import org .junit .Test ;
3233import org .junit .runner .RunWith ;
3334import org .mockito .Mock ;
35+ import org .mockito .invocation .InvocationOnMock ;
3436import org .mockito .junit .MockitoJUnitRunner ;
37+ import org .mockito .stubbing .Answer ;
3538
3639@ RunWith (MockitoJUnitRunner .class )
3740public class DefaultControllerTest {
@@ -67,23 +70,34 @@ public void testStartingStoppingController() throws InterruptedException {
6770 testController .setWorkerThreadPool (Executors .newScheduledThreadPool (1 ));
6871
6972 Request request1 = new Request ("test1" );
70- when (mockReconciler .reconcile (request1 )).thenReturn (new Result (false ));
73+ final Semaphore latch = new Semaphore (1 );
74+ latch .acquire ();
75+ when (mockReconciler .reconcile (request1 ))
76+ .thenAnswer (
77+ new Answer () {
78+ public Object answer (InvocationOnMock invocation ) {
79+ latch .release ();
80+ return new Result (false );
81+ }
82+ });
7183
7284 // emit an event when the controller hasn't started
7385 workQueue .add (request1 );
86+ // I don't love sleeping here, but we're waiting for something we don't expect
87+ // to happen, so there's no good way to do it other than sleep (that I can think of)
7488 cooldown ();
7589 verify (mockReconciler , times (0 )).reconcile (request1 );
7690
7791 controllerThead .submit (testController ::run );
78-
79- cooldown ();
92+ latch .acquire ();
8093 verify (mockReconciler , times (1 )).reconcile (request1 );
8194
8295 testController .shutdown ();
8396 Request request2 = new Request ("test2" );
8497
8598 // emit an event after the controller has shutdown
8699 workQueue .add (request2 );
100+ // as above wrt sleep
87101 cooldown ();
88102 verify (mockReconciler , times (0 )).reconcile (request2 );
89103 }
@@ -92,8 +106,18 @@ public void testStartingStoppingController() throws InterruptedException {
92106 public void testControllerWontStartBeforeReady () throws InterruptedException {
93107
94108 Request request1 = new Request ("test1" );
95- when ( mockReconciler . reconcile ( request1 )). thenReturn ( new Result ( false ) );
109+ final Semaphore latch = new Semaphore ( 1 );
96110
111+ when (mockReconciler .reconcile (request1 ))
112+ .thenAnswer (
113+ new Answer () {
114+ public Object answer (InvocationOnMock invocation ) {
115+ latch .release ();
116+ return new Result (false );
117+ }
118+ });
119+
120+ latch .acquire ();
97121 AtomicBoolean ready = new AtomicBoolean (false );
98122 DefaultController testController =
99123 new DefaultController ("" , mockReconciler , workQueue , () -> ready .get ());
@@ -105,12 +129,13 @@ public void testControllerWontStartBeforeReady() throws InterruptedException {
105129
106130 // emit an event when the controller hasn't been ready
107131 workQueue .add (request1 );
132+ // As above wrt sleep
108133 cooldown ();
109134
110135 verify (mockReconciler , times (0 )).reconcile (request1 );
111136
112137 ready .set (true );
113- cooldown ();
138+ latch . acquire ();
114139 verify (mockReconciler , times (1 )).reconcile (request1 );
115140 }
116141
@@ -120,18 +145,23 @@ public void testControllerKeepsWorkingWhenReconcilerAbortsWithRuntimeException()
120145 AtomicBoolean aborts = new AtomicBoolean (true );
121146 AtomicBoolean resumed = new AtomicBoolean (false );
122147 List <Request > finishedRequests = new ArrayList <>();
148+ final Semaphore latch = new Semaphore (1 );
123149 DefaultController testController =
124150 new DefaultController (
125151 "" ,
126152 new Reconciler () {
127153 @ Override
128154 public Result reconcile (Request request ) {
129- if (aborts .get ()) {
130- throw new RuntimeException ("Oops!!" );
155+ try {
156+ if (aborts .get ()) {
157+ throw new RuntimeException ("Oops!!" );
158+ }
159+ resumed .set (true );
160+ finishedRequests .add (request );
161+ return new Result (false );
162+ } finally {
163+ latch .release ();
131164 }
132- resumed .set (true );
133- finishedRequests .add (request );
134- return new Result (false );
135165 }
136166 },
137167 workQueue );
@@ -142,13 +172,13 @@ public Result reconcile(Request request) {
142172
143173 Request request1 = new Request ("test1" );
144174 workQueue .add (request1 );
145- cooldown ();
175+ latch . acquire ();
146176
147177 aborts .set (false );
148178 // emit another event, the previous one has been backoff'd
149179 Request request2 = new Request ("test2" );
150180 workQueue .add (request2 );
151- cooldown ();
181+ latch . acquire ();
152182 testController .shutdown ();
153183
154184 assertTrue (resumed .get ());
0 commit comments