BentelerYidaSyncServiceTest.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. package com.malk.benteler.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.malk.benteler.config.BentelerYidaConf;
  4. import com.malk.benteler.dto.EiamBatchItemResult;
  5. import com.malk.benteler.dto.EiamBatchOperation;
  6. import com.malk.benteler.dto.EiamBatchResult;
  7. import com.malk.benteler.dto.EiamBatchStage;
  8. import com.malk.benteler.dto.EiamFormSyncResult;
  9. import com.malk.benteler.dto.EiamUpdateUserItem;
  10. import com.malk.server.aliwork.YDAuth;
  11. import com.malk.server.aliwork.YDConf;
  12. import com.malk.server.aliwork.YDParam;
  13. import com.malk.server.common.McException;
  14. import com.malk.service.aliwork.YDClient_Form;
  15. import com.malk.service.aliwork.YDService;
  16. import org.junit.Before;
  17. import org.junit.Test;
  18. import org.mockito.ArgumentCaptor;
  19. import java.util.ArrayList;
  20. import java.util.Arrays;
  21. import java.util.Collections;
  22. import java.util.HashMap;
  23. import java.util.List;
  24. import java.util.Map;
  25. import static org.junit.Assert.assertEquals;
  26. import static org.junit.Assert.assertFalse;
  27. import static org.junit.Assert.assertTrue;
  28. import static org.mockito.ArgumentMatchers.any;
  29. import static org.mockito.ArgumentMatchers.anyMap;
  30. import static org.mockito.ArgumentMatchers.anyString;
  31. import static org.mockito.ArgumentMatchers.isNull;
  32. import static org.mockito.Mockito.mock;
  33. import static org.mockito.Mockito.never;
  34. import static org.mockito.Mockito.times;
  35. import static org.mockito.Mockito.verify;
  36. import static org.mockito.Mockito.when;
  37. /**
  38. * {@link BentelerYidaSyncService} 单实例同步闭环测试。
  39. */
  40. public class BentelerYidaSyncServiceTest {
  41. private YDClient_Form ydClientForm;
  42. private YDService ydService;
  43. private EiamLocalService eiamLocalService;
  44. private BentelerDingTalkSyncTaskService dingTalkSyncTaskService;
  45. private BentelerYidaConf conf;
  46. private BentelerYidaSyncService service;
  47. @Before
  48. public void setUp() {
  49. ydClientForm = mock(YDClient_Form.class);
  50. ydService = mock(YDService.class);
  51. eiamLocalService = mock(EiamLocalService.class);
  52. dingTalkSyncTaskService = mock(BentelerDingTalkSyncTaskService.class);
  53. conf = TestBentelerYidaConf.create();
  54. YDConf ydConf = new YDConf();
  55. ydConf.setAppType("APP_TEST");
  56. ydConf.setSystemToken("TOKEN_TEST");
  57. service = new BentelerYidaSyncService(ydClientForm, ydService, ydConf, conf,
  58. new BentelerYidaFormMapper(conf), eiamLocalService, dingTalkSyncTaskService);
  59. }
  60. @Test
  61. public void syncCreate_queriesInstanceAndWritesBackFullRowsAndStatistics() {
  62. Map<String, Object> formData = new HashMap<>();
  63. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  64. formData.put(conf.getOnboardingTableFieldId(), Arrays.asList(
  65. createRow("人员一", "13800000001"),
  66. createRow("人员二", "13800000002")));
  67. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  68. .thenReturn(instance(formData));
  69. when(eiamLocalService.batchCreate(any())).thenReturn(batchResult(
  70. EiamBatchOperation.CREATE, true, false));
  71. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  72. .thenReturn(Collections.emptyMap());
  73. EiamFormSyncResult result = service.syncCreate("form_test");
  74. assertTrue(result.isWritebackSuccess());
  75. assertEquals(2, result.getTotal());
  76. assertEquals(1, result.getSuccessCount());
  77. ArgumentCaptor<String> jsonCaptor = ArgumentCaptor.forClass(String.class);
  78. verify(ydClientForm).updateForm(any(YDAuth.class), anyString(),
  79. jsonCaptor.capture(), anyMap());
  80. Map<String, Object> update = JSON.parseObject(jsonCaptor.getValue(), Map.class);
  81. List<Map<String, Object>> rows = (List<Map<String, Object>>) update.get(
  82. conf.getOnboardingTableFieldId());
  83. assertEquals(2, rows.size());
  84. assertEquals("成功", rows.get(0).get(conf.getDetailStatusFieldId()));
  85. assertEquals("失败", rows.get(1).get(conf.getDetailStatusFieldId()));
  86. assertEquals(2, ((Number) update.get(conf.getTotalFieldId())).intValue());
  87. assertEquals("人员二 - 执行失败", update.get(conf.getFailureMessageFieldId()));
  88. }
  89. @Test
  90. public void syncCreate_afterWritebackEnqueuesOutsourcingCompanyForSuccessfulRows() {
  91. Map<String, Object> formData = new HashMap<>();
  92. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  93. formData.put(conf.getOnboardingOutsourcingCompanyFieldId(), "众川");
  94. formData.put(conf.getOnboardingTableFieldId(), Collections.singletonList(
  95. createRow("人员一", "13800000001")));
  96. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  97. .thenReturn(instance(formData));
  98. when(eiamLocalService.batchCreate(any())).thenReturn(batchResultWithUserId(
  99. EiamBatchOperation.CREATE, "user_1", true));
  100. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  101. .thenReturn(Collections.emptyMap());
  102. service.syncCreate("form_create");
  103. verify(dingTalkSyncTaskService).enqueueRosterUpdate("form_create", 0, "user_1", "众川");
  104. }
  105. @Test
  106. public void syncUpdate_afterWritebackEnqueuesNonBlankOutsourcingCompany() {
  107. Map<String, Object> row = new HashMap<>();
  108. row.put(conf.getUpdateEmployeeFieldId() + "_id", Collections.singletonList("user_1"));
  109. Map<String, Object> formData = new HashMap<>();
  110. formData.put(conf.getUpdateContentFieldId(),
  111. Collections.singletonList(BentelerYidaFormMapper.UPDATE_PHONE));
  112. formData.put(conf.getUpdateOutsourcingCompanyFieldId(), "翰辉");
  113. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  114. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  115. .thenReturn(instance(formData));
  116. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(
  117. EiamBatchOperation.UPDATE, true));
  118. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  119. .thenReturn(Collections.emptyMap());
  120. service.syncUpdate("form_update");
  121. verify(dingTalkSyncTaskService).enqueueRosterUpdate("form_update", 0, "user_1", "翰辉");
  122. }
  123. @Test
  124. public void syncUpdate_tianjinProbationConfirmationEnqueuesRosterClear() {
  125. Map<String, Object> row = new HashMap<>();
  126. row.put(conf.getUpdateEmployeeFieldId() + "_id", Collections.singletonList("user_1"));
  127. Map<String, Object> formData = new HashMap<>();
  128. formData.put(conf.getUpdateContentFieldId(),
  129. Collections.singletonList(BentelerYidaFormMapper.UPDATE_PHONE));
  130. formData.put(conf.getUpdateFactoryFieldId(), "BATJ II");
  131. formData.put(conf.getUpdateProbationConfirmationFieldId(), "是");
  132. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  133. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  134. .thenReturn(instance(formData));
  135. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(EiamBatchOperation.UPDATE, true));
  136. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  137. .thenReturn(Collections.emptyMap());
  138. service.syncUpdate("form_update");
  139. verify(dingTalkSyncTaskService).enqueueRosterClear("form_update", 0, "user_1");
  140. }
  141. @Test
  142. public void syncUpdate_addDepartmentEnqueuesContactPrimaryDepartmentUpdate() {
  143. Map<String, Object> row = new HashMap<>();
  144. row.put(conf.getUpdateEmployeeFieldId() + "_id", Collections.singletonList("user_1"));
  145. Map<String, Object> formData = new HashMap<>();
  146. formData.put(conf.getUpdateContentFieldId(),
  147. Collections.singletonList(BentelerYidaFormMapper.ADD_ORG));
  148. formData.put(conf.getUpdateOrganizationalUnitIdFieldId(), "ou_target");
  149. formData.put(conf.getUpdateDingTalkDepartmentFieldId(), Collections.singletonList("100"));
  150. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  151. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  152. .thenReturn(instance(formData));
  153. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(EiamBatchOperation.UPDATE, true));
  154. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  155. .thenReturn(Collections.emptyMap());
  156. service.syncUpdate("form_update");
  157. verify(dingTalkSyncTaskService).enqueueContactPrimaryDepartmentUpdate(
  158. "form_update", 0, "user_1", 100L);
  159. }
  160. @Test
  161. public void syncCreate_blankOutsourcingCompanyDoesNotEnqueueTask() {
  162. Map<String, Object> formData = new HashMap<>();
  163. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  164. formData.put(conf.getOnboardingOutsourcingCompanyFieldId(), " ");
  165. formData.put(conf.getOnboardingTableFieldId(), Collections.singletonList(
  166. createRow("人员一", "13800000001")));
  167. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  168. .thenReturn(instance(formData));
  169. when(eiamLocalService.batchCreate(any())).thenReturn(batchResultWithUserId(
  170. EiamBatchOperation.CREATE, "user_1", true));
  171. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  172. .thenReturn(Collections.emptyMap());
  173. service.syncCreate("form_blank");
  174. verify(dingTalkSyncTaskService, never()).enqueueRosterUpdate(anyString(),
  175. org.mockito.ArgumentMatchers.anyInt(), anyString(), anyString());
  176. }
  177. @Test
  178. public void syncCreate_writebackFailureReturnsExecutionResultWithoutRetryingEiam() {
  179. Map<String, Object> formData = new HashMap<>();
  180. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  181. formData.put(conf.getOnboardingTableFieldId(), Collections.singletonList(
  182. createRow("人员一", "13800000001")));
  183. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  184. .thenReturn(instance(formData));
  185. when(eiamLocalService.batchCreate(any())).thenReturn(batchResult(
  186. EiamBatchOperation.CREATE, true));
  187. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  188. .thenThrow(new IllegalStateException("writeback failed"));
  189. EiamFormSyncResult result = service.syncCreate("form_test");
  190. assertFalse(result.isWritebackSuccess());
  191. assertEquals(1, result.getSuccessCount());
  192. verify(eiamLocalService).batchCreate(any());
  193. verify(ydClientForm, times(1)).updateForm(any(YDAuth.class), anyString(),
  194. anyString(), anyMap());
  195. }
  196. @Test
  197. public void syncCreate_versionConflictRetriesWritebackWithoutRetryingEiam() {
  198. Map<String, Object> formData = new HashMap<>();
  199. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  200. formData.put(conf.getOnboardingTableFieldId(), Collections.singletonList(
  201. createRow("人员一", "13800000001")));
  202. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  203. .thenReturn(instance(formData), instance(formData));
  204. when(eiamLocalService.batchCreate(any())).thenReturn(batchResult(
  205. EiamBatchOperation.CREATE, true));
  206. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  207. .thenThrow(new McException("YIDA_ERROR",
  208. "宜搭服务内部异常信息:实例数据已修改,请刷新当前页面"))
  209. .thenReturn(Collections.emptyMap());
  210. EiamFormSyncResult result = service.syncCreate("form_version_conflict");
  211. assertTrue(result.isWritebackSuccess());
  212. assertEquals("冲突重试回写成功", result.getWritebackMessage());
  213. verify(eiamLocalService, times(1)).batchCreate(any());
  214. verify(ydClientForm, times(2)).updateForm(any(YDAuth.class), anyString(),
  215. anyString(), anyMap());
  216. }
  217. @Test
  218. @SuppressWarnings("unchecked")
  219. public void syncUpdate_readsEiamOrganizationalUnitIdDirectly() {
  220. Map<String, Object> row = new HashMap<>();
  221. row.put(conf.getUpdateEmployeeFieldId() + "_id",
  222. Collections.singletonList("user_1"));
  223. Map<String, Object> formData = new HashMap<>();
  224. formData.put(conf.getUpdateContentFieldId(),
  225. Collections.singletonList(BentelerYidaFormMapper.REPLACE_PRIMARY_ORG));
  226. formData.put(conf.getUpdateOrganizationalUnitIdFieldId(), "ou_target");
  227. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  228. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  229. .thenReturn(instance(formData));
  230. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(
  231. EiamBatchOperation.UPDATE, true));
  232. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  233. .thenReturn(Collections.emptyMap());
  234. EiamFormSyncResult result = service.syncUpdate("form_update");
  235. assertEquals(1, result.getSuccessCount());
  236. ArgumentCaptor<List> itemsCaptor = ArgumentCaptor.forClass(List.class);
  237. verify(eiamLocalService).batchUpdate(itemsCaptor.capture());
  238. List<EiamUpdateUserItem> items = (List<EiamUpdateUserItem>) itemsCaptor.getValue();
  239. assertEquals("user_1", items.get(0).getUserId());
  240. assertEquals("ou_target", items.get(0).getPrimaryOrganizationalUnitId());
  241. }
  242. @Test
  243. public void syncUpdate_replaceAndAddDepartment_rejectsBeforeEiamCall() {
  244. Map<String, Object> row = new HashMap<>();
  245. row.put(conf.getUpdateEmployeeFieldId() + "_id",
  246. Collections.singletonList("user_1"));
  247. Map<String, Object> formData = new HashMap<>();
  248. formData.put(conf.getUpdateContentFieldId(), Arrays.asList(
  249. BentelerYidaFormMapper.REPLACE_PRIMARY_ORG,
  250. BentelerYidaFormMapper.ADD_ORG));
  251. formData.put(conf.getUpdateOrganizationalUnitIdFieldId(), "ou_target");
  252. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  253. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  254. .thenReturn(instance(formData));
  255. try {
  256. service.syncUpdate("form_update_conflict");
  257. } catch (McException ex) {
  258. assertEquals("EIAM_UPDATE_CONTENT_CONFLICT", ex.getCode());
  259. assertEquals("替换部门和增加部门不能同时选择", ex.getMessage());
  260. verify(eiamLocalService, never()).batchUpdate(any());
  261. return;
  262. }
  263. throw new AssertionError("替换部门和增加部门同时选择时应拒绝请求");
  264. }
  265. @Test
  266. @SuppressWarnings("unchecked")
  267. public void syncUpdate_phoneOnly_doesNotRequireOrganizationalUnit() {
  268. Map<String, Object> row = new HashMap<>();
  269. row.put(conf.getUpdateEmployeeFieldId() + "_id",
  270. Collections.singletonList("user_1"));
  271. row.put(conf.getUpdatePhoneFieldId(), "17612168216");
  272. Map<String, Object> formData = new HashMap<>();
  273. formData.put(conf.getUpdateContentFieldId(),
  274. Collections.singletonList(BentelerYidaFormMapper.UPDATE_PHONE));
  275. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  276. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  277. .thenReturn(instance(formData));
  278. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(
  279. EiamBatchOperation.UPDATE, true));
  280. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  281. .thenReturn(Collections.emptyMap());
  282. EiamFormSyncResult result = service.syncUpdate("form_update_phone");
  283. assertEquals(1, result.getSuccessCount());
  284. ArgumentCaptor<List> itemsCaptor = ArgumentCaptor.forClass(List.class);
  285. verify(eiamLocalService).batchUpdate(itemsCaptor.capture());
  286. List<EiamUpdateUserItem> items = (List<EiamUpdateUserItem>) itemsCaptor.getValue();
  287. assertEquals("17612168216", items.get(0).getUsername());
  288. assertEquals(null, items.get(0).getPrimaryOrganizationalUnitId());
  289. }
  290. @Test
  291. public void syncUpdate_exactlyFiftyRowsQueriesDetailsWithConfiguredFormUuid() {
  292. List<Map<String, Object>> inlineRows = new ArrayList<>();
  293. for (int index = 0; index < 50; index++) {
  294. Map<String, Object> row = new HashMap<>();
  295. row.put(conf.getUpdateEmployeeFieldId() + "_id",
  296. Collections.singletonList("user_" + index));
  297. inlineRows.add(row);
  298. }
  299. Map<String, Object> formData = new HashMap<>();
  300. formData.put(conf.getUpdateContentFieldId(),
  301. Collections.singletonList(BentelerYidaFormMapper.UPDATE_PHONE));
  302. formData.put(conf.getUpdateTableFieldId(), inlineRows);
  303. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  304. .thenReturn(instance(formData));
  305. when(ydService.queryDetails(any(YDParam.class))).thenReturn((List) inlineRows);
  306. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(
  307. EiamBatchOperation.UPDATE, successFlags(50)));
  308. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  309. .thenReturn(Collections.emptyMap());
  310. service.syncUpdate("form_update_50");
  311. ArgumentCaptor<YDParam> paramCaptor = ArgumentCaptor.forClass(YDParam.class);
  312. verify(ydService).queryDetails(paramCaptor.capture());
  313. assertEquals("FORM-UPDATE", paramCaptor.getValue().getFormUuid());
  314. }
  315. @Test
  316. public void syncDelete_exactlyFiftyRowsFallsBackWhenDetailQueryThrowsNpe() {
  317. List<Map<String, Object>> inlineRows = new ArrayList<>();
  318. for (int index = 0; index < 50; index++) {
  319. Map<String, Object> row = new HashMap<>();
  320. row.put(conf.getOffboardingEmployeeFieldId() + "_id",
  321. Collections.singletonList("user_" + index));
  322. inlineRows.add(row);
  323. }
  324. Map<String, Object> formData = new HashMap<>();
  325. formData.put(conf.getOffboardingTableFieldId(), inlineRows);
  326. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  327. .thenReturn(instance(formData));
  328. when(ydService.queryDetails(any(YDParam.class))).thenThrow(new NullPointerException());
  329. when(eiamLocalService.batchDelete(any())).thenReturn(batchResult(
  330. EiamBatchOperation.DELETE, successFlags(50)));
  331. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  332. .thenReturn(Collections.emptyMap());
  333. EiamFormSyncResult result = service.syncDelete("form_delete");
  334. assertEquals(50, result.getTotal());
  335. verify(ydService).queryDetails(any(YDParam.class));
  336. }
  337. @Test
  338. public void syncDelete_lessThanFiftyRowsUsesInlineDetails() {
  339. List<Map<String, Object>> inlineRows = new ArrayList<>();
  340. for (int index = 0; index < 49; index++) {
  341. Map<String, Object> row = new HashMap<>();
  342. row.put(conf.getOffboardingEmployeeFieldId() + "_id",
  343. Collections.singletonList("user_" + index));
  344. inlineRows.add(row);
  345. }
  346. Map<String, Object> formData = new HashMap<>();
  347. formData.put(conf.getOffboardingTableFieldId(), inlineRows);
  348. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  349. .thenReturn(instance(formData));
  350. when(eiamLocalService.batchDelete(any())).thenReturn(batchResult(
  351. EiamBatchOperation.DELETE, successFlags(49)));
  352. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  353. .thenReturn(Collections.emptyMap());
  354. EiamFormSyncResult result = service.syncDelete("form_delete_49");
  355. assertEquals(49, result.getTotal());
  356. verify(ydService, never()).queryDetails(any(YDParam.class));
  357. }
  358. private Map<String, Object> createRow(String name, String phone) {
  359. Map<String, Object> row = new HashMap<>();
  360. row.put(conf.getOnboardingNameFieldId(), name);
  361. row.put(conf.getOnboardingPhoneFieldId(), phone);
  362. return row;
  363. }
  364. private Map<String, Object> instance(Map<String, Object> formData) {
  365. Map<String, Object> instance = new HashMap<>();
  366. instance.put("formData", formData);
  367. return instance;
  368. }
  369. private boolean[] successFlags(int size) {
  370. boolean[] flags = new boolean[size];
  371. Arrays.fill(flags, true);
  372. return flags;
  373. }
  374. private EiamBatchResult batchResult(EiamBatchOperation operation, boolean... successFlags) {
  375. List<EiamBatchItemResult> items = new ArrayList<>();
  376. for (int index = 0; index < successFlags.length; index++) {
  377. items.add(EiamBatchItemResult.builder().index(index).success(successFlags[index])
  378. .stage(EiamBatchStage.COMPLETED).build());
  379. }
  380. return EiamBatchResult.of(operation, items);
  381. }
  382. private EiamBatchResult batchResultWithUserId(EiamBatchOperation operation, String userId,
  383. boolean success) {
  384. return EiamBatchResult.of(operation, Collections.singletonList(EiamBatchItemResult.builder()
  385. .index(0).userId(userId).success(success).stage(EiamBatchStage.COMPLETED).build()));
  386. }
  387. }