mirror of https://github.com/EasyAbp/EShop.git
6 changed files with 338 additions and 14 deletions
@ -0,0 +1,192 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Products.Products; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using NSubstitute; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Orders; |
|||
|
|||
public class InventoryReductionResultTests : OrdersDomainTestBase |
|||
{ |
|||
private Order Order1 { get; set; } |
|||
|
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
var orderRepository = Substitute.For<IOrderRepository>(); |
|||
Order1 = new Order( |
|||
OrderTestData.Order1Id, |
|||
null, |
|||
OrderTestData.Store1Id, |
|||
Guid.NewGuid(), |
|||
"CNY", |
|||
1m, |
|||
0m, |
|||
1.5m, |
|||
1.5m, |
|||
null, |
|||
null); |
|||
Order1.OrderLines.Add(new OrderLine( |
|||
OrderTestData.OrderLine1Id, |
|||
OrderTestData.Product1Id, |
|||
OrderTestData.ProductSku1Id, |
|||
null, |
|||
DateTime.Now, |
|||
null, |
|||
"Default", |
|||
"Default", |
|||
null, |
|||
"Product 1", |
|||
null, |
|||
null, |
|||
null, |
|||
"CNY", |
|||
0.5m, |
|||
1m, |
|||
0m, |
|||
1m, |
|||
2 |
|||
)); |
|||
Order1.OrderExtraFees.Add(new OrderExtraFee( |
|||
OrderTestData.Order1Id, |
|||
"Name", |
|||
"Key", |
|||
0.3m |
|||
)); |
|||
|
|||
orderRepository.GetAsync(OrderTestData.Order1Id).Returns(Task.FromResult(Order1)); |
|||
|
|||
services.AddTransient(_ => orderRepository); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Cancel_Order_If_Reduction_Failed_After_Placed() |
|||
{ |
|||
typeof(Order).GetProperty(nameof(Order.CanceledTime))!.SetValue(Order1, null); |
|||
typeof(Order).GetProperty(nameof(Order.CancellationReason))!.SetValue(Order1, null); |
|||
Order1.SetReducedInventoryAfterPlacingTime(null); |
|||
Order1.SetReducedInventoryAfterPaymentTime(null); |
|||
Order1.SetOrderStatus(OrderStatus.Pending); |
|||
Order1.SetPaymentId(null); |
|||
Order1.SetPaidTime(null); |
|||
|
|||
var handler = ServiceProvider.GetRequiredService<ProductInventoryReductionEventHandler>(); |
|||
|
|||
await handler.HandleEventAsync(new ProductInventoryReductionAfterOrderPlacedResultEto() |
|||
{ |
|||
TenantId = null, |
|||
OrderId = OrderTestData.Order1Id, |
|||
IsSuccess = false |
|||
}); |
|||
|
|||
Order1.CanceledTime.ShouldNotBeNull(); |
|||
Order1.CancellationReason.ShouldBe(OrdersConsts.InventoryReductionFailedAutoCancellationReason); |
|||
Order1.ReducedInventoryAfterPlacingTime.ShouldBeNull(); |
|||
Order1.ReducedInventoryAfterPaymentTime.ShouldBeNull(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Not_Cancel_Order_If_Reduction_Succeeded_After_Placed() |
|||
{ |
|||
typeof(Order).GetProperty(nameof(Order.CanceledTime))!.SetValue(Order1, null); |
|||
typeof(Order).GetProperty(nameof(Order.CancellationReason))!.SetValue(Order1, null); |
|||
Order1.SetReducedInventoryAfterPlacingTime(null); |
|||
Order1.SetReducedInventoryAfterPaymentTime(null); |
|||
Order1.SetOrderStatus(OrderStatus.Pending); |
|||
Order1.SetPaymentId(null); |
|||
Order1.SetPaidTime(null); |
|||
|
|||
var handler = ServiceProvider.GetRequiredService<ProductInventoryReductionEventHandler>(); |
|||
|
|||
await handler.HandleEventAsync(new ProductInventoryReductionAfterOrderPlacedResultEto() |
|||
{ |
|||
TenantId = null, |
|||
OrderId = OrderTestData.Order1Id, |
|||
IsSuccess = true |
|||
}); |
|||
|
|||
Order1.CanceledTime.ShouldBeNull(); |
|||
Order1.CancellationReason.ShouldBeNull(); |
|||
Order1.ReducedInventoryAfterPlacingTime.ShouldNotBeNull(); |
|||
Order1.ReducedInventoryAfterPaymentTime.ShouldBeNull(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Cancel_Order_And_Refund_If_Reduction_Failed_After_Paid() |
|||
{ |
|||
typeof(Order).GetProperty(nameof(Order.CanceledTime))!.SetValue(Order1, null); |
|||
typeof(Order).GetProperty(nameof(Order.CancellationReason))!.SetValue(Order1, null); |
|||
Order1.SetReducedInventoryAfterPlacingTime(DateTime.Now); |
|||
Order1.SetReducedInventoryAfterPaymentTime(null); |
|||
Order1.SetOrderStatus(OrderStatus.Processing); |
|||
Order1.SetPaymentId(OrderTestData.Payment1Id); |
|||
Order1.SetPaidTime(DateTime.Now); |
|||
|
|||
var handler = ServiceProvider.GetRequiredService<ProductInventoryReductionEventHandler>(); |
|||
|
|||
await handler.HandleEventAsync(new ProductInventoryReductionAfterOrderPaidResultEto() |
|||
{ |
|||
TenantId = null, |
|||
OrderId = OrderTestData.Order1Id, |
|||
IsSuccess = false |
|||
}); |
|||
|
|||
var eventData = TestRefundOrderEventHandler.LastEto; |
|||
TestRefundOrderEventHandler.LastEto = null; |
|||
eventData.ShouldNotBeNull(); |
|||
eventData.DisplayReason.ShouldBe(OrdersConsts.InventoryReductionFailedAutoCancellationReason); |
|||
eventData.StaffRemark.ShouldBe(OrdersConsts.InventoryReductionFailedAutoCancellationReason); |
|||
eventData.CustomerRemark.ShouldBe(OrdersConsts.InventoryReductionFailedAutoCancellationReason); |
|||
eventData.PaymentId.ShouldBe(OrderTestData.Payment1Id); |
|||
eventData.TenantId.ShouldBeNull(); |
|||
eventData.OrderId.ShouldBe(OrderTestData.Order1Id); |
|||
|
|||
eventData.OrderLines.Count.ShouldBe(1); |
|||
var orderLine = eventData.OrderLines[0]; |
|||
orderLine.OrderLineId.ShouldBe(OrderTestData.OrderLine1Id); |
|||
orderLine.Quantity.ShouldBe(2); |
|||
orderLine.TotalAmount.ShouldBe(1m); |
|||
|
|||
eventData.OrderExtraFees.Count.ShouldBe(1); |
|||
var orderExtraFee = eventData.OrderExtraFees[0]; |
|||
orderExtraFee.Name.ShouldBe("Name"); |
|||
orderExtraFee.Key.ShouldBe("Key"); |
|||
orderExtraFee.TotalAmount.ShouldBe(0.3m); |
|||
|
|||
Order1.CanceledTime.ShouldNotBeNull(); |
|||
Order1.CancellationReason.ShouldBe(OrdersConsts.InventoryReductionFailedAutoCancellationReason); |
|||
Order1.ReducedInventoryAfterPlacingTime.ShouldNotBeNull(); |
|||
Order1.ReducedInventoryAfterPaymentTime.ShouldBeNull(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Not_Cancel_And_Refund_Order_If_Reduction_Succeeded_After_Paid() |
|||
{ |
|||
typeof(Order).GetProperty(nameof(Order.CanceledTime))!.SetValue(Order1, null); |
|||
typeof(Order).GetProperty(nameof(Order.CancellationReason))!.SetValue(Order1, null); |
|||
Order1.SetReducedInventoryAfterPlacingTime(DateTime.Now); |
|||
Order1.SetReducedInventoryAfterPaymentTime(null); |
|||
Order1.SetOrderStatus(OrderStatus.Processing); |
|||
Order1.SetPaymentId(OrderTestData.Payment1Id); |
|||
Order1.SetPaidTime(DateTime.Now); |
|||
|
|||
var handler = ServiceProvider.GetRequiredService<ProductInventoryReductionEventHandler>(); |
|||
|
|||
await handler.HandleEventAsync(new ProductInventoryReductionAfterOrderPaidResultEto() |
|||
{ |
|||
TenantId = null, |
|||
OrderId = OrderTestData.Order1Id, |
|||
IsSuccess = true |
|||
}); |
|||
|
|||
var eventData = TestRefundOrderEventHandler.LastEto; |
|||
TestRefundOrderEventHandler.LastEto = null; |
|||
eventData.ShouldBeNull(); |
|||
|
|||
Order1.CanceledTime.ShouldBeNull(); |
|||
Order1.CancellationReason.ShouldBeNull(); |
|||
Order1.ReducedInventoryAfterPlacingTime.ShouldNotBeNull(); |
|||
Order1.ReducedInventoryAfterPaymentTime.ShouldNotBeNull(); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Payments.Refunds; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.EventBus.Distributed; |
|||
|
|||
namespace EasyAbp.EShop.Orders.Orders; |
|||
|
|||
public class TestRefundOrderEventHandler : IDistributedEventHandler<RefundOrderEto>, ITransientDependency |
|||
{ |
|||
public static RefundOrderEto LastEto { get; set; } |
|||
|
|||
public Task HandleEventAsync(RefundOrderEto eventData) |
|||
{ |
|||
LastEto = eventData; |
|||
|
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using EasyAbp.EShop.Payments.Payments; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using NSubstitute; |
|||
using NSubstitute.Core; |
|||
using Shouldly; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Json; |
|||
using Xunit; |
|||
|
|||
namespace EasyAbp.EShop.Payments.Refunds; |
|||
|
|||
public class RefundOrderEventHandlerTests : PaymentsDomainTestBase |
|||
{ |
|||
private readonly IJsonSerializer _jsonSerializer; |
|||
|
|||
public RefundOrderEventHandlerTests() |
|||
{ |
|||
_jsonSerializer = ServiceProvider.GetRequiredService<IJsonSerializer>(); |
|||
} |
|||
|
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
MockPaymentRepository(services); |
|||
} |
|||
|
|||
private static void MockPaymentRepository(IServiceCollection services) |
|||
{ |
|||
var paymentRepository = Substitute.For<IPaymentRepository>(); |
|||
|
|||
Payment Payment1Returns(CallInfo _) |
|||
{ |
|||
var paymentType = typeof(Payment); |
|||
var paymentItemType = typeof(PaymentItem); |
|||
|
|||
var paymentItem = Activator.CreateInstance(paymentItemType, true) as PaymentItem; |
|||
paymentItem.ShouldNotBeNull(); |
|||
paymentItemType.GetProperty(nameof(PaymentItem.Id))?.SetValue(paymentItem, PaymentsTestData.PaymentItem1); |
|||
paymentItemType.GetProperty(nameof(PaymentItem.ActualPaymentAmount))?.SetValue(paymentItem, 1m); |
|||
paymentItemType.GetProperty(nameof(PaymentItem.ItemType)) |
|||
?.SetValue(paymentItem, PaymentsConsts.PaymentItemType); |
|||
paymentItemType.GetProperty(nameof(PaymentItem.ItemKey)) |
|||
?.SetValue(paymentItem, PaymentsTestData.Order1.ToString()); |
|||
paymentItemType.GetProperty(nameof(PaymentItem.StoreId)) |
|||
?.SetValue(paymentItem, PaymentsTestData.Store1); |
|||
|
|||
var payment = Activator.CreateInstance(paymentType, true) as Payment; |
|||
payment.ShouldNotBeNull(); |
|||
paymentType.GetProperty(nameof(Payment.Id))?.SetValue(payment, PaymentsTestData.Payment1); |
|||
paymentType.GetProperty(nameof(Payment.Currency))?.SetValue(payment, "CNY"); |
|||
paymentType.GetProperty(nameof(Payment.ActualPaymentAmount))?.SetValue(payment, 1m); |
|||
paymentType.GetProperty(nameof(Payment.PaymentItems)) |
|||
?.SetValue(payment, new List<PaymentItem> { paymentItem }); |
|||
|
|||
return payment; |
|||
} |
|||
|
|||
paymentRepository.GetAsync(PaymentsTestData.Payment1).Returns(Payment1Returns); |
|||
paymentRepository.FindAsync(PaymentsTestData.Payment1).Returns(Payment1Returns); |
|||
|
|||
services.AddTransient(_ => paymentRepository); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Refund_Order() |
|||
{ |
|||
var handler = ServiceProvider.GetRequiredService<RefundOrderEventHandler>(); |
|||
|
|||
var eto = new RefundOrderEto(null, PaymentsTestData.Order1, PaymentsTestData.Store1, |
|||
PaymentsTestData.Payment1, "Test", null, null); |
|||
|
|||
eto.OrderLines.Add(new OrderLineRefundInfoModel |
|||
{ |
|||
OrderLineId = PaymentsTestData.OrderLine1, |
|||
Quantity = 2, |
|||
TotalAmount = 0.4m |
|||
}); |
|||
|
|||
eto.OrderExtraFees.Add(new OrderExtraFeeRefundInfoModel |
|||
{ |
|||
Name = "Name", |
|||
Key = "Key", |
|||
TotalAmount = 0.6m |
|||
}); |
|||
|
|||
await handler.HandleEventAsync(eto); |
|||
|
|||
var eventData = TestRefundPaymentEventHandler.LastEto; |
|||
TestRefundPaymentEventHandler.LastEto = null; |
|||
eventData.ShouldNotBeNull(); |
|||
eventData.CreateRefundInput.RefundItems.Count.ShouldBe(1); |
|||
|
|||
var refundItem = eventData.CreateRefundInput.RefundItems[0]; |
|||
refundItem.GetProperty<Guid?>(nameof(RefundItem.OrderId)).ShouldBe(PaymentsTestData.Order1); |
|||
|
|||
var orderLines = |
|||
_jsonSerializer.Deserialize<List<OrderLineRefundInfoModel>>( |
|||
refundItem.GetProperty<string>(nameof(RefundItem.OrderLines))); |
|||
|
|||
orderLines.Count.ShouldBe(1); |
|||
orderLines[0].OrderLineId.ShouldBe(PaymentsTestData.OrderLine1); |
|||
orderLines[0].Quantity.ShouldBe(2); |
|||
orderLines[0].TotalAmount.ShouldBe(0.4m); |
|||
|
|||
var orderExtraFees = |
|||
_jsonSerializer.Deserialize<List<OrderExtraFeeRefundInfoModel>>( |
|||
refundItem.GetProperty<string>(nameof(RefundItem.OrderExtraFees))); |
|||
|
|||
orderExtraFees.Count.ShouldBe(1); |
|||
orderExtraFees[0].Name.ShouldBe("Name"); |
|||
orderExtraFees[0].Key.ShouldBe("Key"); |
|||
orderExtraFees[0].TotalAmount.ShouldBe(0.6m); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue