BusinessLicenseAndCouponTest.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package com.xuekairui.gateway;
  2. import org.junit.jupiter.api.*;
  3. import org.springframework.http.MediaType;
  4. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
  5. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
  6. /**
  7. * 营业执照和优惠券模块测试
  8. *
  9. * 覆盖场景:
  10. * 1. 营业执照上传/查询(可选功能)
  11. * 2. 优惠券获取/使用
  12. * 3. 用户等级查询
  13. */
  14. @DisplayName("营业执照和优惠券模块测试")
  15. @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
  16. class BusinessLicenseAndCouponTest extends GatewayBaseTest {
  17. private String userToken() {
  18. return generateAccessToken(1L, "13800138000");
  19. }
  20. // ==================== 营业执照上传(可选功能)====================
  21. @Test
  22. @Order(1)
  23. @DisplayName("POST /api/business-license/upload - 上传营业执照")
  24. void uploadBusinessLicense_shouldSucceed() throws Exception {
  25. String body = """
  26. {
  27. "licenseImageUrl": "https://oss.example.com/license/test.jpg",
  28. "creditCode": "91110000XXXXXXXXXX",
  29. "pharmacyName": "测试大药房",
  30. "legalPerson": "张三"
  31. }
  32. """;
  33. mockMvc.perform(post("/api/business-license/upload")
  34. .header("Authorization", "Bearer " + userToken())
  35. .contentType(MediaType.APPLICATION_JSON)
  36. .content(body))
  37. .andExpect(status().isOk())
  38. .andExpect(jsonPath("$.code").value(200));
  39. }
  40. @Test
  41. @Order(2)
  42. @DisplayName("POST /api/business-license/upload - 缺少必填字段应返回400")
  43. void uploadBusinessLicense_missingFields_shouldReturnBadRequest() throws Exception {
  44. String body = """
  45. {
  46. "pharmacyName": "测试大药房"
  47. }
  48. """;
  49. mockMvc.perform(post("/api/business-license/upload")
  50. .header("Authorization", "Bearer " + userToken())
  51. .contentType(MediaType.APPLICATION_JSON)
  52. .content(body))
  53. .andExpect(status().isBadRequest());
  54. }
  55. @Test
  56. @Order(3)
  57. @DisplayName("POST /api/business-license/upload - 无Token应返回401")
  58. void uploadBusinessLicense_withoutToken_shouldReturn401() throws Exception {
  59. mockMvc.perform(post("/api/business-license/upload")
  60. .contentType(MediaType.APPLICATION_JSON)
  61. .content("{}"))
  62. .andExpect(status().isUnauthorized());
  63. }
  64. @Test
  65. @Order(4)
  66. @DisplayName("GET /api/business-license/info - 查询营业执照信息")
  67. void getBusinessLicenseInfo_shouldReturnInfo() throws Exception {
  68. mockMvc.perform(get("/api/business-license/info")
  69. .header("Authorization", "Bearer " + userToken()))
  70. .andExpect(status().isOk())
  71. .andExpect(jsonPath("$.code").value(200));
  72. }
  73. @Test
  74. @Order(5)
  75. @DisplayName("GET /api/business-license/info - 未上传应返回空或null")
  76. void getBusinessLicenseInfo_notUploaded_shouldReturnEmpty() throws Exception {
  77. mockMvc.perform(get("/api/business-license/info")
  78. .header("Authorization", "Bearer " + userToken()))
  79. .andExpect(status().isOk());
  80. // 可能返回data为null或空对象,但不应报错
  81. }
  82. @Test
  83. @Order(6)
  84. @DisplayName("GET /api/business-license/info - 无Token应返回401")
  85. void getBusinessLicenseInfo_withoutToken_shouldReturn401() throws Exception {
  86. mockMvc.perform(get("/api/business-license/info"))
  87. .andExpect(status().isUnauthorized());
  88. }
  89. // ==================== 优惠券管理 ====================
  90. @Test
  91. @Order(10)
  92. @DisplayName("GET /api/coupon/my - 获取我的优惠券列表")
  93. void getMyCoupons_shouldReturnList() throws Exception {
  94. mockMvc.perform(get("/api/coupon/my")
  95. .header("Authorization", "Bearer " + userToken()))
  96. .andExpect(status().isOk())
  97. .andExpect(jsonPath("$.code").value(200))
  98. .andExpect(jsonPath("$.data").isArray());
  99. }
  100. @Test
  101. @Order(11)
  102. @DisplayName("GET /api/coupon/my?status=0 - 筛选未使用优惠券")
  103. void getMyCoupons_filterByStatus_shouldWork() throws Exception {
  104. mockMvc.perform(get("/api/coupon/my?status=0")
  105. .header("Authorization", "Bearer " + userToken()))
  106. .andExpect(status().isOk())
  107. .andExpect(jsonPath("$.data").isArray());
  108. }
  109. @Test
  110. @Order(12)
  111. @DisplayName("GET /api/coupon/my?status=1 - 筛选已使用优惠券")
  112. void getMyCoupons_filterByUsedStatus_shouldWork() throws Exception {
  113. mockMvc.perform(get("/api/coupon/my?status=1")
  114. .header("Authorization", "Bearer " + userToken()))
  115. .andExpect(status().isOk());
  116. }
  117. @Test
  118. @Order(13)
  119. @DisplayName("GET /api/coupon/my?status=2 - 筛选已过期优惠券")
  120. void getMyCoupons_filterByExpiredStatus_shouldWork() throws Exception {
  121. mockMvc.perform(get("/api/coupon/my?status=2")
  122. .header("Authorization", "Bearer " + userToken()))
  123. .andExpect(status().isOk());
  124. }
  125. @Test
  126. @Order(14)
  127. @DisplayName("GET /api/coupon/my - 无Token应返回401")
  128. void getMyCoupons_withoutToken_shouldReturn401() throws Exception {
  129. mockMvc.perform(get("/api/coupon/my"))
  130. .andExpect(status().isUnauthorized());
  131. }
  132. @Test
  133. @Order(15)
  134. @DisplayName("GET /api/coupon/my/available?type=CRAWLER - 获取可用优惠券")
  135. void getAvailableCoupons_shouldReturnList() throws Exception {
  136. mockMvc.perform(get("/api/coupon/my/available?type=CRAWLER")
  137. .header("Authorization", "Bearer " + userToken()))
  138. .andExpect(status().isOk())
  139. .andExpect(jsonPath("$.code").value(200))
  140. .andExpect(jsonPath("$.data").isArray());
  141. }
  142. @Test
  143. @Order(16)
  144. @DisplayName("GET /api/coupon/my/available - 无Token应返回401")
  145. void getAvailableCoupons_withoutToken_shouldReturn401() throws Exception {
  146. mockMvc.perform(get("/api/coupon/my/available"))
  147. .andExpect(status().isUnauthorized());
  148. }
  149. // ==================== 用户等级查询 ====================
  150. @Test
  151. @Order(20)
  152. @DisplayName("GET /api/level/list - 获取等级列表(公开)")
  153. void getLevelList_shouldReturnList() throws Exception {
  154. mockMvc.perform(get("/api/level/list"))
  155. .andExpect(status().isOk())
  156. .andExpect(jsonPath("$.code").value(200))
  157. .andExpect(jsonPath("$.data").isArray());
  158. }
  159. @Test
  160. @Order(21)
  161. @DisplayName("GET /api/level/list - 等级应包含必要字段")
  162. void getLevelList_shouldContainRequiredFields() throws Exception {
  163. mockMvc.perform(get("/api/level/list"))
  164. .andExpect(status().isOk())
  165. .andExpect(result -> {
  166. String content = result.getResponse().getContentAsString();
  167. com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
  168. var json = mapper.readTree(content);
  169. var data = json.get("data");
  170. if (data.isArray() && data.size() > 0) {
  171. var firstLevel = data.get(0);
  172. assert firstLevel.has("id") : "应包含id";
  173. assert firstLevel.has("levelName") : "应包含levelName";
  174. assert firstLevel.has("levelCode") : "应包含levelCode";
  175. assert firstLevel.has("crawlerQuota") : "应包含crawlerQuota";
  176. assert firstLevel.has("monthlyQuota") : "应包含monthlyQuota";
  177. assert firstLevel.has("yearlyQuota") : "应包含yearlyQuota";
  178. assert firstLevel.has("maxConcurrent") : "应包含maxConcurrent";
  179. }
  180. });
  181. }
  182. @Test
  183. @Order(22)
  184. @DisplayName("GET /api/level/{id} - 获取等级详情")
  185. void getLevelDetail_shouldReturnDetail() throws Exception {
  186. mockMvc.perform(get("/api/level/1")
  187. .header("Authorization", "Bearer " + userToken()))
  188. .andExpect(status().isOk())
  189. .andExpect(jsonPath("$.code").value(200));
  190. }
  191. @Test
  192. @Order(23)
  193. @DisplayName("GET /api/level/{id} - 不存在的等级应返回404")
  194. void getLevelDetail_nonExistent_shouldReturn404() throws Exception {
  195. mockMvc.perform(get("/api/level/999")
  196. .header("Authorization", "Bearer " + userToken()))
  197. .andExpect(status().isNotFound());
  198. }
  199. @Test
  200. @Order(24)
  201. @DisplayName("GET /api/level/my - 获取当前用户等级")
  202. void getMyLevel_shouldReturnLevel() throws Exception {
  203. mockMvc.perform(get("/api/level/my")
  204. .header("Authorization", "Bearer " + userToken()))
  205. .andExpect(status().isOk())
  206. .andExpect(jsonPath("$.code").value(200));
  207. }
  208. @Test
  209. @Order(25)
  210. @DisplayName("GET /api/level/my - 无Token应返回401")
  211. void getMyLevel_withoutToken_shouldReturn401() throws Exception {
  212. mockMvc.perform(get("/api/level/my"))
  213. .andExpect(status().isUnauthorized());
  214. }
  215. // ==================== Token刷新 ====================
  216. @Test
  217. @Order(30)
  218. @DisplayName("POST /api/auth/refresh - 刷新Token")
  219. void refreshToken_shouldReturnNewTokens() throws Exception {
  220. // 注意:这个测试可能需要一个有效的refresh token
  221. // 由于是集成测试,我们验证接口可访问性
  222. mockMvc.perform(post("/api/auth/refresh")
  223. .header("Authorization", "Bearer " + userToken())
  224. .contentType(MediaType.APPLICATION_JSON)
  225. .content("{\"refreshToken\":\"test_refresh_token\"}"))
  226. .andExpect(status().isOk());
  227. // 如果token无效,会返回业务错误,但不应401
  228. }
  229. @Test
  230. @Order(31)
  231. @DisplayName("POST /api/auth/refresh - 空请求体应返回400")
  232. void refreshToken_emptyBody_shouldReturnBadRequest() throws Exception {
  233. mockMvc.perform(post("/api/auth/refresh")
  234. .contentType(MediaType.APPLICATION_JSON)
  235. .content(""))
  236. .andExpect(status().isBadRequest());
  237. }
  238. }