-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathTestDataFactory.cs
132 lines (109 loc) · 5.82 KB
/
TestDataFactory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using MyWarehouse.Domain.Common.ValueObjects.Mass;
using MyWarehouse.Domain.Common.ValueObjects.Money;
using MyWarehouse.Domain.Partners;
using MyWarehouse.Domain.Products;
using MyWarehouse.Domain.Transactions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyWarehouse.Application.IntegrationTests
{
public class TestDataFactory
{
private readonly TestData _data;
public TestDataFactory(TestData data) => _data = data;
/// <summary>
/// Creates the requested number of products, and adds them to the database.
/// </summary>
/// <param name="productOverrides">Action to invoke on each product created, to allow property customization before saving.</param>
/// <returns>The list of created products.</returns>
public async Task<List<Product>> AddProducts(int howMany, Action<(int index, Product product)> productOverrides = null)
{
var products = new Product[howMany];
for (int i = 0; i < howMany; i++)
{
var product = new Product(
name: "Product" + i,
description: "Description" + i,
price: new Money((i+1) * 10, Currency.USD),
mass: new Mass(i+1, MassUnit.Kilogram));
productOverrides?.Invoke((i, product));
products[i] = product;
}
await _data.AddRangeAsync(products);
return products.ToList();
}
/// <summary>
/// Creates the requested number of partners, and adds them to the database.
/// </summary>
/// <param name="partnerOverrides">Action to invoke on each partner created, to allow property customization before saving.</param>
/// <returns>The list of created partners.</returns>
public async Task<List<Partner>> AddPartners(int howMany, Action<(int index, Partner partner)> partnerOverrides = null)
{
var partners = new Partner[howMany];
for (int i = 0; i < howMany; i++)
{
var partner = new Partner(
name: "Partner Number" + (i+1),
address: new Address(
country: "Canada",
city: "Toronto",
street: (i+1) + " Test street",
zipcode: string.Join("", Enumerable.Range(i+1, 6)).Substring(0, 6))
);
partnerOverrides?.Invoke((i, partner));
partners[i] = partner;
}
await _data.AddRangeAsync(partners);
return partners.ToList();
}
/// <summary>
/// Creates a procurement transaction.
/// </summary>
/// <param name="partner">The partner to create a transaction with. If not provided, a new partner will be created.</param>
/// <param name="createNewProducts">If true, new products will be created for all transaction lines. If false, products will be read from database.</param>
public async Task<Transaction> CreateProcurementTransaction(int numberOfLines, Partner partner = null, bool createNewProducts = true)
{
partner ??= (await AddPartners(1)).First();
var products = createNewProducts
? await AddProducts(numberOfLines)
: await _data.GetAllAsync<Product>();
if (products.Count < numberOfLines)
throw new ArgumentException($"Cannot create {numberOfLines} transaction lines, " +
$"because there are only {products.Count} products. " +
$"You can set '{createNewProducts}' to true to create the necessary products.", nameof(numberOfLines));
int quantity = 1;
var lines = products.Take(numberOfLines).Select(p => (p, quantity++)).ToList();
var transaction = partner.ProcureFrom(lines);
await _data.AddAsync(transaction);
return transaction;
}
public async Task<Transaction> CreateSalesTransaction(Partner partner, IEnumerable<Product> productsToSell, float ratioOfStockToSell = 1f)
{
if (ratioOfStockToSell <= 0 || ratioOfStockToSell > 1)
throw new ArgumentException("Ratio must be greater than 0 and less than 1.", nameof(ratioOfStockToSell));
if (productsToSell.Any(p => p.NumberInStock == 0))
throw new ArgumentException("All products must have a stock to be able to sell them.", nameof(ratioOfStockToSell));
var lines = productsToSell.Select(p => (p, (int)Math.Ceiling(p.NumberInStock * ratioOfStockToSell))).ToList();
var transaction = partner.SellTo(lines);
await _data.AddAsync(transaction);
return transaction;
}
/// <summary>
/// Creates a sales transaction by automatically creating first a backing procurement transaction
/// which in turn creates the necessary products for the transaction.
/// </summary>
/// <param name="partner">The partner to create a transaction with. If not provided, a new partner will be created.</param>
/// <returns>Returns the sales transaction created. The result in the database will be
/// the added products, the procurement transaction, and the sales transaction.</returns>
public async Task<Transaction> CreateSalesTransaction(int numberOfLines, Partner partner = null)
{
partner ??= (await AddPartners(1)).First();
var procurement = await CreateProcurementTransaction(numberOfLines, partner);
var salesTransaction = partner.SellTo(procurement.TransactionLines.Select(p => (p.Product, p.Quantity)));
await _data.AddAsync(salesTransaction);
return salesTransaction;
}
}
}