test project created
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
using Distribution.Features.Order;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Infra.UoW;
|
||||
using Distribution.Models;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Distribution.Tests.Services;
|
||||
|
||||
public class OrderServiceTests
|
||||
{
|
||||
private readonly Mock<IOrderRepository> _repo = new();
|
||||
private readonly Mock<IUnitOfWork> _uow = new();
|
||||
private readonly Mock<ICurrentUserService> _currentUser = new();
|
||||
private readonly Mock<IScopeAccessService> _scopeAccess = new();
|
||||
private readonly OrderService _sut;
|
||||
|
||||
public OrderServiceTests()
|
||||
{
|
||||
_sut = new OrderService(_repo.Object, _uow.Object, _currentUser.Object, _scopeAccess.Object);
|
||||
}
|
||||
|
||||
private static Order ActiveOrder(Guid storeId) => new()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
FK_StoreId = storeId,
|
||||
OrderDate = DateTime.Now,
|
||||
TotalAmount = 100,
|
||||
IsActive = true
|
||||
};
|
||||
|
||||
private void SetupGlobalUser(Guid userId)
|
||||
{
|
||||
_currentUser.Setup(u => u.UserId).Returns(userId);
|
||||
_currentUser.Setup(u => u.RoleLevel).Returns(50);
|
||||
}
|
||||
|
||||
private void SetupScopedUser(Guid userId)
|
||||
{
|
||||
_currentUser.Setup(u => u.UserId).Returns(userId);
|
||||
_currentUser.Setup(u => u.RoleLevel).Returns(10);
|
||||
}
|
||||
|
||||
// GetAllAsync
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_GlobalUser_ReturnsAllActiveOrders()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var storeA = Guid.NewGuid();
|
||||
var storeB = Guid.NewGuid();
|
||||
SetupGlobalUser(userId);
|
||||
var orders = new List<Order> { ActiveOrder(storeA), ActiveOrder(storeB) };
|
||||
_repo.Setup(r => r.GetAllAsync()).ReturnsAsync(orders);
|
||||
_repo.Setup(r => r.GetItemsByOrderIdAsync(It.IsAny<Guid>())).ReturnsAsync([]);
|
||||
|
||||
var result = await _sut.GetAllAsync();
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_ScopedUser_FiltersToAccessibleStores()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var accessibleStore = Guid.NewGuid();
|
||||
var restrictedStore = Guid.NewGuid();
|
||||
SetupScopedUser(userId);
|
||||
_scopeAccess.Setup(s => s.GetAccessibleStoreIdsAsync(userId)).ReturnsAsync([accessibleStore]);
|
||||
var orders = new List<Order> { ActiveOrder(accessibleStore), ActiveOrder(restrictedStore) };
|
||||
_repo.Setup(r => r.GetAllAsync()).ReturnsAsync(orders);
|
||||
_repo.Setup(r => r.GetItemsByOrderIdAsync(It.IsAny<Guid>())).ReturnsAsync([]);
|
||||
|
||||
var result = await _sut.GetAllAsync();
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Equal(accessibleStore, result[0].StoreId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAllAsync_FiltersOutInactiveOrders()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
SetupGlobalUser(userId);
|
||||
var inactiveOrder = ActiveOrder(Guid.NewGuid());
|
||||
inactiveOrder.IsActive = false;
|
||||
_repo.Setup(r => r.GetAllAsync()).ReturnsAsync([inactiveOrder]);
|
||||
_repo.Setup(r => r.GetItemsByOrderIdAsync(It.IsAny<Guid>())).ReturnsAsync([]);
|
||||
|
||||
var result = await _sut.GetAllAsync();
|
||||
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
// GetByIdAsync
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_ReturnsNull_WhenOrderNotFound()
|
||||
{
|
||||
SetupGlobalUser(Guid.NewGuid());
|
||||
_repo.Setup(r => r.GetByIdAsync(It.IsAny<Guid>())).ReturnsAsync((Order?)null);
|
||||
|
||||
var result = await _sut.GetByIdAsync(Guid.NewGuid());
|
||||
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_ReturnsNull_WhenUserLacksStoreScope()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var storeId = Guid.NewGuid();
|
||||
SetupScopedUser(userId);
|
||||
_repo.Setup(r => r.GetByIdAsync(It.IsAny<Guid>())).ReturnsAsync(ActiveOrder(storeId));
|
||||
_scopeAccess.Setup(s => s.HasStoreScopeAsync(userId, storeId)).ReturnsAsync(false);
|
||||
|
||||
var result = await _sut.GetByIdAsync(Guid.NewGuid());
|
||||
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_ReturnsOrder_WhenGlobalUser()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var order = ActiveOrder(Guid.NewGuid());
|
||||
SetupGlobalUser(userId);
|
||||
_repo.Setup(r => r.GetByIdAsync(order.Id)).ReturnsAsync(order);
|
||||
_repo.Setup(r => r.GetItemsByOrderIdAsync(order.Id)).ReturnsAsync([]);
|
||||
|
||||
var result = await _sut.GetByIdAsync(order.Id);
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(order.Id, result.Id);
|
||||
}
|
||||
|
||||
// CreateAsync
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_ReturnsNull_WhenUserLacksStoreScope()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var storeId = Guid.NewGuid();
|
||||
SetupScopedUser(userId);
|
||||
_scopeAccess.Setup(s => s.HasStoreScopeAsync(userId, storeId)).ReturnsAsync(false);
|
||||
|
||||
var result = await _sut.CreateAsync(
|
||||
new CreateOrderRequest(storeId, DateTime.Now, 100, []));
|
||||
|
||||
Assert.Null(result);
|
||||
_uow.Verify(u => u.BeginAsync(default), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_CreatesOrder_WhenGlobalUser()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var storeId = Guid.NewGuid();
|
||||
SetupGlobalUser(userId);
|
||||
_repo.Setup(r => r.AddAsync(It.IsAny<Order>())).Returns(Task.CompletedTask);
|
||||
_repo.Setup(r => r.AddItemsAsync(It.IsAny<IEnumerable<OrderItem>>())).Returns(Task.CompletedTask);
|
||||
|
||||
var result = await _sut.CreateAsync(
|
||||
new CreateOrderRequest(storeId, DateTime.Now, 250, []));
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(storeId, result.StoreId);
|
||||
Assert.Equal(250, result.TotalAmount);
|
||||
_uow.Verify(u => u.BeginAsync(default), Times.Once);
|
||||
_uow.Verify(u => u.CommitAsync(default), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_Rollbacks_OnException()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
SetupGlobalUser(userId);
|
||||
_repo.Setup(r => r.AddAsync(It.IsAny<Order>())).ThrowsAsync(new Exception("db error"));
|
||||
|
||||
await Assert.ThrowsAsync<Exception>(() =>
|
||||
_sut.CreateAsync(new CreateOrderRequest(Guid.NewGuid(), DateTime.Now, 100, [])));
|
||||
|
||||
_uow.Verify(u => u.RollbackAsync(default), Times.Once);
|
||||
_uow.Verify(u => u.CommitAsync(default), Times.Never);
|
||||
}
|
||||
|
||||
// DeleteAsync
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_ReturnsFalse_WhenOrderNotFound()
|
||||
{
|
||||
SetupGlobalUser(Guid.NewGuid());
|
||||
_repo.Setup(r => r.GetByIdAsync(It.IsAny<Guid>())).ReturnsAsync((Order?)null);
|
||||
|
||||
var result = await _sut.DeleteAsync(Guid.NewGuid());
|
||||
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_ReturnsFalse_WhenUserLacksStoreScope()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var storeId = Guid.NewGuid();
|
||||
SetupScopedUser(userId);
|
||||
_repo.Setup(r => r.GetByIdAsync(It.IsAny<Guid>())).ReturnsAsync(ActiveOrder(storeId));
|
||||
_scopeAccess.Setup(s => s.HasStoreScopeAsync(userId, storeId)).ReturnsAsync(false);
|
||||
|
||||
var result = await _sut.DeleteAsync(Guid.NewGuid());
|
||||
|
||||
Assert.False(result);
|
||||
_uow.Verify(u => u.BeginAsync(default), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAsync_RemovesOrder_WhenAuthorized()
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
var order = ActiveOrder(Guid.NewGuid());
|
||||
SetupGlobalUser(userId);
|
||||
_repo.Setup(r => r.GetByIdAsync(order.Id)).ReturnsAsync(order);
|
||||
|
||||
var result = await _sut.DeleteAsync(order.Id);
|
||||
|
||||
Assert.True(result);
|
||||
_repo.Verify(r => r.Remove(order), Times.Once);
|
||||
_uow.Verify(u => u.CommitAsync(default), Times.Once);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user