BentelerYidaSyncServiceTest.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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.service.aliwork.YDClient_Form;
  14. import com.malk.service.aliwork.YDService;
  15. import org.junit.Before;
  16. import org.junit.Test;
  17. import org.mockito.ArgumentCaptor;
  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;
  24. import static org.junit.Assert.assertEquals;
  25. import static org.junit.Assert.assertFalse;
  26. import static org.junit.Assert.assertTrue;
  27. import static org.mockito.ArgumentMatchers.any;
  28. import static org.mockito.ArgumentMatchers.anyMap;
  29. import static org.mockito.ArgumentMatchers.anyString;
  30. import static org.mockito.ArgumentMatchers.isNull;
  31. import static org.mockito.Mockito.mock;
  32. import static org.mockito.Mockito.never;
  33. import static org.mockito.Mockito.verify;
  34. import static org.mockito.Mockito.when;
  35. /**
  36. * {@link BentelerYidaSyncService} 单实例同步闭环测试。
  37. */
  38. public class BentelerYidaSyncServiceTest {
  39. private YDClient_Form ydClientForm;
  40. private YDService ydService;
  41. private EiamLocalService eiamLocalService;
  42. private BentelerYidaConf conf;
  43. private BentelerYidaSyncService service;
  44. @Before
  45. public void setUp() {
  46. ydClientForm = mock(YDClient_Form.class);
  47. ydService = mock(YDService.class);
  48. eiamLocalService = mock(EiamLocalService.class);
  49. conf = TestBentelerYidaConf.create();
  50. YDConf ydConf = new YDConf();
  51. ydConf.setAppType("APP_TEST");
  52. ydConf.setSystemToken("TOKEN_TEST");
  53. service = new BentelerYidaSyncService(ydClientForm, ydService, ydConf, conf,
  54. new BentelerYidaFormMapper(conf), eiamLocalService);
  55. }
  56. @Test
  57. public void syncCreate_queriesInstanceAndWritesBackFullRowsAndStatistics() {
  58. Map<String, Object> formData = new HashMap<>();
  59. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  60. formData.put(conf.getOnboardingTableFieldId(), Arrays.asList(
  61. createRow("人员一", "13800000001"),
  62. createRow("人员二", "13800000002")));
  63. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  64. .thenReturn(instance(formData));
  65. when(eiamLocalService.batchCreate(any())).thenReturn(batchResult(
  66. EiamBatchOperation.CREATE, true, false));
  67. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  68. .thenReturn(Collections.emptyMap());
  69. EiamFormSyncResult result = service.syncCreate("form_test");
  70. assertTrue(result.isWritebackSuccess());
  71. assertEquals(2, result.getTotal());
  72. assertEquals(1, result.getSuccessCount());
  73. ArgumentCaptor<String> jsonCaptor = ArgumentCaptor.forClass(String.class);
  74. verify(ydClientForm).updateForm(any(YDAuth.class), anyString(),
  75. jsonCaptor.capture(), anyMap());
  76. Map<String, Object> update = JSON.parseObject(jsonCaptor.getValue(), Map.class);
  77. List<Map<String, Object>> rows = (List<Map<String, Object>>) update.get(
  78. conf.getOnboardingTableFieldId());
  79. assertEquals(2, rows.size());
  80. assertEquals("成功", rows.get(0).get(conf.getDetailStatusFieldId()));
  81. assertEquals("失败", rows.get(1).get(conf.getDetailStatusFieldId()));
  82. assertEquals(2, ((Number) update.get(conf.getTotalFieldId())).intValue());
  83. assertEquals("人员二 - 执行失败", update.get(conf.getFailureMessageFieldId()));
  84. }
  85. @Test
  86. public void syncCreate_writebackFailureReturnsExecutionResultWithoutRetryingEiam() {
  87. Map<String, Object> formData = new HashMap<>();
  88. formData.put(conf.getOnboardingOrganizationalUnitIdFieldId(), "ou_technical");
  89. formData.put(conf.getOnboardingTableFieldId(), Collections.singletonList(
  90. createRow("人员一", "13800000001")));
  91. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  92. .thenReturn(instance(formData));
  93. when(eiamLocalService.batchCreate(any())).thenReturn(batchResult(
  94. EiamBatchOperation.CREATE, true));
  95. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  96. .thenThrow(new IllegalStateException("writeback failed"));
  97. EiamFormSyncResult result = service.syncCreate("form_test");
  98. assertFalse(result.isWritebackSuccess());
  99. assertEquals(1, result.getSuccessCount());
  100. verify(eiamLocalService).batchCreate(any());
  101. }
  102. @Test
  103. @SuppressWarnings("unchecked")
  104. public void syncUpdate_readsEiamOrganizationalUnitIdDirectly() {
  105. Map<String, Object> row = new HashMap<>();
  106. row.put(conf.getUpdateEmployeeFieldId() + "_id",
  107. Collections.singletonList("user_1"));
  108. Map<String, Object> formData = new HashMap<>();
  109. formData.put(conf.getUpdateContentFieldId(),
  110. Collections.singletonList(BentelerYidaFormMapper.UPDATE_PRIMARY_ORG));
  111. formData.put(conf.getUpdateOrganizationalUnitIdFieldId(), "ou_target");
  112. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  113. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  114. .thenReturn(instance(formData));
  115. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(
  116. EiamBatchOperation.UPDATE, true));
  117. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  118. .thenReturn(Collections.emptyMap());
  119. EiamFormSyncResult result = service.syncUpdate("form_update");
  120. assertEquals(1, result.getSuccessCount());
  121. ArgumentCaptor<List> itemsCaptor = ArgumentCaptor.forClass(List.class);
  122. verify(eiamLocalService).batchUpdate(itemsCaptor.capture());
  123. List<EiamUpdateUserItem> items = (List<EiamUpdateUserItem>) itemsCaptor.getValue();
  124. assertEquals("user_1", items.get(0).getUserId());
  125. assertEquals("ou_target", items.get(0).getPrimaryOrganizationalUnitId());
  126. }
  127. @Test
  128. @SuppressWarnings("unchecked")
  129. public void syncUpdate_phoneOnly_doesNotRequireOrganizationalUnit() {
  130. Map<String, Object> row = new HashMap<>();
  131. row.put(conf.getUpdateEmployeeFieldId() + "_id",
  132. Collections.singletonList("user_1"));
  133. row.put(conf.getUpdatePhoneFieldId(), "17612168216");
  134. Map<String, Object> formData = new HashMap<>();
  135. formData.put(conf.getUpdateContentFieldId(),
  136. Collections.singletonList(BentelerYidaFormMapper.UPDATE_PHONE));
  137. formData.put(conf.getUpdateTableFieldId(), Collections.singletonList(row));
  138. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  139. .thenReturn(instance(formData));
  140. when(eiamLocalService.batchUpdate(any())).thenReturn(batchResult(
  141. EiamBatchOperation.UPDATE, true));
  142. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  143. .thenReturn(Collections.emptyMap());
  144. EiamFormSyncResult result = service.syncUpdate("form_update_phone");
  145. assertEquals(1, result.getSuccessCount());
  146. ArgumentCaptor<List> itemsCaptor = ArgumentCaptor.forClass(List.class);
  147. verify(eiamLocalService).batchUpdate(itemsCaptor.capture());
  148. List<EiamUpdateUserItem> items = (List<EiamUpdateUserItem>) itemsCaptor.getValue();
  149. assertEquals("17612168216", items.get(0).getUsername());
  150. assertEquals(null, items.get(0).getPrimaryOrganizationalUnitId());
  151. }
  152. @Test
  153. public void syncDelete_exactlyFiftyRowsFallsBackWhenDetailQueryThrowsNpe() {
  154. List<Map<String, Object>> inlineRows = new ArrayList<>();
  155. for (int index = 0; index < 50; index++) {
  156. Map<String, Object> row = new HashMap<>();
  157. row.put(conf.getOffboardingEmployeeFieldId() + "_id",
  158. Collections.singletonList("user_" + index));
  159. inlineRows.add(row);
  160. }
  161. Map<String, Object> formData = new HashMap<>();
  162. formData.put(conf.getOffboardingTableFieldId(), inlineRows);
  163. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  164. .thenReturn(instance(formData));
  165. when(ydService.queryDetails(any(YDParam.class))).thenThrow(new NullPointerException());
  166. when(eiamLocalService.batchDelete(any())).thenReturn(batchResult(
  167. EiamBatchOperation.DELETE, successFlags(50)));
  168. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  169. .thenReturn(Collections.emptyMap());
  170. EiamFormSyncResult result = service.syncDelete("form_delete");
  171. assertEquals(50, result.getTotal());
  172. verify(ydService).queryDetails(any(YDParam.class));
  173. }
  174. @Test
  175. public void syncDelete_lessThanFiftyRowsUsesInlineDetails() {
  176. List<Map<String, Object>> inlineRows = new ArrayList<>();
  177. for (int index = 0; index < 49; index++) {
  178. Map<String, Object> row = new HashMap<>();
  179. row.put(conf.getOffboardingEmployeeFieldId() + "_id",
  180. Collections.singletonList("user_" + index));
  181. inlineRows.add(row);
  182. }
  183. Map<String, Object> formData = new HashMap<>();
  184. formData.put(conf.getOffboardingTableFieldId(), inlineRows);
  185. when(ydClientForm.getForm(any(YDAuth.class), anyString(), isNull()))
  186. .thenReturn(instance(formData));
  187. when(eiamLocalService.batchDelete(any())).thenReturn(batchResult(
  188. EiamBatchOperation.DELETE, successFlags(49)));
  189. when(ydClientForm.updateForm(any(YDAuth.class), anyString(), anyString(), anyMap()))
  190. .thenReturn(Collections.emptyMap());
  191. EiamFormSyncResult result = service.syncDelete("form_delete_49");
  192. assertEquals(49, result.getTotal());
  193. verify(ydService, never()).queryDetails(any(YDParam.class));
  194. }
  195. private Map<String, Object> createRow(String name, String phone) {
  196. Map<String, Object> row = new HashMap<>();
  197. row.put(conf.getOnboardingNameFieldId(), name);
  198. row.put(conf.getOnboardingPhoneFieldId(), phone);
  199. return row;
  200. }
  201. private Map<String, Object> instance(Map<String, Object> formData) {
  202. Map<String, Object> instance = new HashMap<>();
  203. instance.put("formData", formData);
  204. return instance;
  205. }
  206. private boolean[] successFlags(int size) {
  207. boolean[] flags = new boolean[size];
  208. Arrays.fill(flags, true);
  209. return flags;
  210. }
  211. private EiamBatchResult batchResult(EiamBatchOperation operation, boolean... successFlags) {
  212. List<EiamBatchItemResult> items = new ArrayList<>();
  213. for (int index = 0; index < successFlags.length; index++) {
  214. items.add(EiamBatchItemResult.builder().index(index).success(successFlags[index])
  215. .stage(EiamBatchStage.COMPLETED).build());
  216. }
  217. return EiamBatchResult.of(operation, items);
  218. }
  219. }