暂存提交
This commit is contained in:
@@ -23,6 +23,7 @@ public class MerchantBatchDraftService {
|
||||
public MerchantBatchDraftDtos.Response create(long tenantId, long userId, String batchKey,
|
||||
List<MerchantBatchDraftDtos.Item> items) {
|
||||
if (!StringUtils.hasText(batchKey)) throw new BizException("必须提供 Idempotency-Key");
|
||||
if (batchKey.trim().length() > 128) throw new BizException("Idempotency-Key 长度不能超过128");
|
||||
if (items == null || items.isEmpty()) throw new BizException("批量草稿不能为空");
|
||||
if (items.size() > MAX_ITEMS) throw new BizException("批量草稿最多 50 条");
|
||||
List<MerchantBatchDraftDtos.Result> results = new ArrayList<>(items.size());
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.baiyue.order.service;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.order.dto.MerchantBatchDraftDtos;
|
||||
import com.baiyue.order.dto.OrderRequests;
|
||||
import com.baiyue.order.entity.OrderEntity;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@SpringJUnitConfig(MerchantBatchDraftService.class)
|
||||
class MerchantBatchDraftServiceTest {
|
||||
@MockBean private MerchantBatchDraftItemService itemService;
|
||||
@Resource private MerchantBatchDraftService service;
|
||||
|
||||
@Test
|
||||
void createsEachRowAndReturnsOrderReferences() {
|
||||
doAnswer(invocation -> order(101L, "FL101", "RK-101"))
|
||||
.doAnswer(invocation -> order(102L, "FL102", "RK-102"))
|
||||
.when(itemService).create(anyLong(), anyLong(), any(), anyString());
|
||||
|
||||
var response = service.create(10L, 20L, "batch-key", List.of(
|
||||
item("row-1"), item("row-2")));
|
||||
|
||||
assertThat(response.total()).isEqualTo(2);
|
||||
assertThat(response.succeeded()).isEqualTo(2);
|
||||
assertThat(response.failed()).isZero();
|
||||
assertThat(response.items()).extracting(MerchantBatchDraftDtos.Result::inboundCode)
|
||||
.containsExactly("RK-101", "RK-102");
|
||||
assertThat(response.items()).extracting(MerchantBatchDraftDtos.Result::index)
|
||||
.containsExactly(0, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void keepsSuccessfulRowsWhenAnotherRowFails() {
|
||||
doAnswer(invocation -> order(101L, "FL101", "RK-101"))
|
||||
.doThrow(new BizException("SKU不能为空"))
|
||||
.when(itemService).create(anyLong(), anyLong(), any(), anyString());
|
||||
|
||||
var response = service.create(10L, 20L, "batch-key", List.of(
|
||||
item("row-1"), item("row-2")));
|
||||
|
||||
assertThat(response.succeeded()).isEqualTo(1);
|
||||
assertThat(response.failed()).isEqualTo(1);
|
||||
assertThat(response.items().get(0).success()).isTrue();
|
||||
assertThat(response.items().get(1).success()).isFalse();
|
||||
assertThat(response.items().get(1).errorMessage()).isEqualTo("SKU不能为空");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsDuplicateRowWithoutCreatingItTwice() {
|
||||
doAnswer(invocation -> order(101L, "FL101", "RK-101"))
|
||||
.when(itemService).create(anyLong(), anyLong(), any(), anyString());
|
||||
|
||||
var response = service.create(10L, 20L, "batch-key", List.of(
|
||||
item("same-row"), item("same-row")));
|
||||
|
||||
assertThat(response.succeeded()).isEqualTo(1);
|
||||
assertThat(response.failed()).isEqualTo(1);
|
||||
assertThat(response.items().get(1).errorCode()).isEqualTo("A0409");
|
||||
verify(itemService).create(anyLong(), anyLong(), any(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void derivesStablePerRowIdempotencyKeys() {
|
||||
String first = MerchantBatchDraftService.derivedKey(" batch-key ", "row-1");
|
||||
String retry = MerchantBatchDraftService.derivedKey("batch-key", "row-1");
|
||||
String anotherRow = MerchantBatchDraftService.derivedKey("batch-key", "row-2");
|
||||
|
||||
assertThat(first).isEqualTo(retry).startsWith("batch-").hasSize(70);
|
||||
assertThat(anotherRow).isNotEqualTo(first);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsInvalidBatchBeforeCreatingRows() {
|
||||
assertThatThrownBy(() -> service.create(10L, 20L, " ", List.of(item("row-1"))))
|
||||
.isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> service.create(10L, 20L, "x".repeat(129), List.of(item("row-1"))))
|
||||
.isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> service.create(10L, 20L, "batch-key", List.of()))
|
||||
.isInstanceOf(BizException.class);
|
||||
verify(itemService, never()).create(anyLong(), anyLong(), any(), anyString());
|
||||
}
|
||||
|
||||
private MerchantBatchDraftDtos.Item item(String rowId) {
|
||||
return new MerchantBatchDraftDtos.Item(rowId, mock(OrderRequests.SaveRequest.class));
|
||||
}
|
||||
|
||||
private OrderEntity order(long id, String orderNo, String inboundCode) {
|
||||
OrderEntity order = new OrderEntity();
|
||||
order.setId(id);
|
||||
order.setOrderNo(orderNo);
|
||||
order.setInboundCode(inboundCode);
|
||||
return order;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user