java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/MasterDataImportTest.java
... ...
@@ -209,12 +209,13 @@ public class MasterDataImportTest {
209 209
SecurityManager securityManager = Mockito.mock(org.apache.shiro.mgt.SecurityManager.class);
210 210
Subject fakeSubject = Mockito.mock(Subject.class);
211 211
// Stub the mock BEFORE installing it as the global SecurityManager to avoid a race
212
- // condition where a background thread (from RacingEventServiceImpl's static
213
- // ScheduledExecutorService) calls SecurityUtils.getSubject(), which triggers
214
- // createSubject() on the mock while Mockito is still in the middle of setting up
215
- // the doReturn().when() stubbing. The background thread consumes/corrupts
216
- // Mockito's doAnswer-style answers on the mock's InvocationContainer, causing
217
- // an AssertionError in InvocationContainerImpl.setMethodForStubbing.
212
+ // condition: SecurityUtils.setSecurityManager() sets a JVM-wide static singleton.
213
+ // Any thread that calls SecurityUtils.getSubject() (when no Subject is bound to its
214
+ // ThreadContext) will trigger securityManager.createSubject(). If that happens between
215
+ // the .when(securityManager) call (which sets pending doAnswer-style answers on the
216
+ // mock's InvocationContainer) and the .createSubject() call (which completes the
217
+ // stubbing), the other thread's call consumes the pending answers first, causing an
218
+ // AssertionError in InvocationContainerImpl.setMethodForStubbing (line 123).
218 219
Mockito.doReturn(fakeSubject).when(securityManager).createSubject(Mockito.any());
219 220
SecurityUtils.setSecurityManager(securityManager);
220 221
Mockito.doReturn(defaultTenant).when(securityService).getServerGroup();
java/com.sap.sailing.server.test/src/com/sap/sailing/server/test/SearchServiceTest.java
... ...
@@ -130,12 +130,13 @@ public class SearchServiceTest {
130 130
SecurityManager securityManager = Mockito.mock(org.apache.shiro.mgt.SecurityManager.class);
131 131
Subject fakeSubject = Mockito.mock(Subject.class);
132 132
// Stub the mock BEFORE installing it as the global SecurityManager to avoid a race
133
- // condition where a background thread (from RacingEventServiceImpl's static
134
- // ScheduledExecutorService) calls SecurityUtils.getSubject(), which triggers
135
- // createSubject() on the mock while Mockito is still in the middle of setting up
136
- // the doReturn().when() stubbing. The background thread consumes/corrupts
137
- // Mockito's doAnswer-style answers on the mock's InvocationContainer, causing
138
- // an AssertionError in InvocationContainerImpl.setMethodForStubbing.
133
+ // condition: SecurityUtils.setSecurityManager() sets a JVM-wide static singleton.
134
+ // Any thread that calls SecurityUtils.getSubject() (when no Subject is bound to its
135
+ // ThreadContext) will trigger securityManager.createSubject(). If that happens between
136
+ // the .when(securityManager) call (which sets pending doAnswer-style answers on the
137
+ // mock's InvocationContainer) and the .createSubject() call (which completes the
138
+ // stubbing), the other thread's call consumes the pending answers first, causing an
139
+ // AssertionError in InvocationContainerImpl.setMethodForStubbing (line 123).
139 140
Mockito.doReturn(fakeSubject).when(securityManager).createSubject(Mockito.any());
140 141
SecurityUtils.setSecurityManager(securityManager);
141 142
Mockito.doReturn(defaultTenant).when(securityService).getServerGroup();