Шаг 20: Unit-тесты
Тесты Domain Layer -- самые быстрые и надёжные. Они не требуют БД, HTTP или DI.
MoneyTests.cs
В проекте OrderManagement.Domain.Tests:
using FluentAssertions;
using OrderManagement.Domain.Exceptions;
using OrderManagement.Domain.ValueObjects;
namespace OrderManagement.Domain.Tests;
public class MoneyTests
{
[Fact]
public void Constructor_ValidAmount_ShouldCreate()
{
var money = new Money(100, "RUB");
money.Amount.Should().Be(100);
money.Currency.Should().Be("RUB");
}
[Fact]
public void Constructor_Negative_ShouldThrow()
{
var act = () => new Money(-1, "RUB");
act.Should().Throw<DomainException>();
}
[Theory]
[InlineData(100, 50, 150)]
[InlineData(0, 0, 0)]
[InlineData(999.99, 0.01, 1000)]
public void Add_SameCurrency_ShouldReturnSum(
decimal a, decimal b, decimal expected)
{
var result = new Money(a, "RUB").Add(new Money(b, "RUB"));
result.Amount.Should().Be(expected);
}
[Fact]
public void Add_DifferentCurrency_ShouldThrow()
{
var act = () => new Money(100, "RUB")
.Add(new Money(50, "USD"));
act.Should().Throw<DomainException>();
}
[Fact]
public void Equality_SameValues_ShouldBeEqual()
{
var a = new Money(100, "RUB");
var b = new Money(100, "RUB");
a.Should().Be(b);
(a == b).Should().BeTrue();
}
}
OrderTests.cs
using FluentAssertions;
using OrderManagement.Domain.Entities;
using OrderManagement.Domain.Enums;
using OrderManagement.Domain.Events;
using OrderManagement.Domain.Exceptions;
using OrderManagement.Domain.ValueObjects;
namespace OrderManagement.Domain.Tests;
public class OrderTests
{
private static ShippingAddress CreateAddress() =>
new("Main St 1", "Moscow", "101000", "Russia");
[Fact]
public void Create_ShouldReturnDraftOrder()
{
var order = Order.Create("cust-001", CreateAddress());
order.Status.Should().Be(OrderStatus.Draft);
order.Items.Should().BeEmpty();
order.DomainEvents.Should().ContainSingle()
.Which.Should().BeOfType<OrderCreatedEvent>();
}
[Fact]
public void AddItem_ShouldRecalculateTotal()
{
var order = Order.Create("cust-001", CreateAddress());
order.AddItem("p1", "Laptop", new Money(75000, "RUB"), 2);
order.Items.Should().HaveCount(1);
order.TotalAmount.Amount.Should().Be(150000);
}
[Fact]
public void Confirm_EmptyOrder_ShouldThrow()
{
var order = Order.Create("cust-001", CreateAddress());
var act = () => order.Confirm();
act.Should().Throw<DomainException>();
}
[Fact]
public void Confirm_WithItems_ShouldChangeStatus()
{
var order = Order.Create("cust-001", CreateAddress());
order.AddItem("p1", "Laptop", new Money(75000, "RUB"), 1);
order.Confirm();
order.Status.Should().Be(OrderStatus.Confirmed);
}
[Fact]
public void AddItem_ToConfirmedOrder_ShouldThrow()
{
var order = Order.Create("cust-001", CreateAddress());
order.AddItem("p1", "Laptop", new Money(75000, "RUB"), 1);
order.Confirm();
var act = () => order.AddItem(
"p2", "Mouse", new Money(1500, "RUB"), 1);
act.Should().Throw<DomainException>();
}
}
Запуск
dotnet test tests/OrderManagement.Domain.Tests