Skip to content

Commit f28662a

Browse files
committed
Add FastMoney test
1 parent 2abf481 commit f28662a

4 files changed

Lines changed: 184 additions & 34 deletions

File tree

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,52 @@
1+
using NodaMoney;
2+
using System.Collections.Frozen;
3+
using System.Diagnostics;
4+
using System.Reflection;
5+
16
namespace NodaMoneyTest;
27

3-
public static partial class MoneyTest
8+
public static class CurrencyCode
49
{
5-
public static class CurrencyCode
6-
{
710

8-
#region Constants & Statics
11+
#region Constants & Statics
12+
13+
// "¥"
14+
public static readonly string CNY = "CNY";
915

10-
// "¥"
11-
public static readonly string CNY = "CNY";
16+
// ""
17+
public static readonly string EUR = "EUR";
1218

13-
// ""
14-
public static readonly string EUR = "EUR";
19+
// "HK$"
20+
public static readonly string HKD = "HKD";
1521

16-
// "HK$"
17-
public static readonly string HKD = "HKD";
22+
// "¥"
23+
public static readonly string JPY = "JPY";
1824

19-
// "¥"
20-
public static readonly string JPY = "JPY";
25+
// "MOP$"
26+
public static readonly string MOP = "MOP";
2127

22-
// "MOP$"
23-
public static readonly string MOP = "MOP";
24-
// "NT$"
25-
public static readonly string TWD = "TWD";
28+
// "NT$"
29+
public static readonly string TWD = "TWD";
2630

27-
// "US$"
28-
public static readonly string USD = "USD";
31+
// "US$"
32+
public static readonly string USD = "USD";
33+
34+
static CurrencyCode()
35+
{
36+
var props = typeof(CurrencyCode).GetFields(BindingFlags.Static | BindingFlags.DeclaredOnly);
2937

30-
#endregion
38+
var list = new List<Currency>();
39+
foreach (var field in props)
40+
{
41+
var value = field.GetValue(null) as string;
42+
Debug.Assert(value is not null, $"{nameof(value)} is null.");
43+
44+
list.Add(Currency.FromCode(value));
45+
}
46+
47+
var dic = list.ToFrozenDictionary(static o => o.Code, o => o);
3148
}
49+
50+
#endregion
51+
3252
}

src/plugins/NodaMoneyTest/MoneyTest.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,31 @@
44

55
namespace NodaMoneyTest;
66

7-
public static partial class MoneyTest
7+
public static class MoneyTest
88
{
99

1010
#region Constants & Statics
1111

1212
public static void DefaultCurrency_Test()
1313
{
14-
var myDefaultContext = MoneyContext.Create(
15-
opt =>
14+
_ = MoneyContext.CreateAndSetDefault(
15+
(options) =>
1616
{
17-
opt.MaxScale = 4;
18-
opt.DefaultCurrency = CurrencyInfo.FromCode(CurrencyCode.CNY);
19-
opt.EnforceZeroCurrencyMatching = true;
17+
options.MaxScale = 4;
18+
options.DefaultCurrency = CurrencyInfo.FromCode(CurrencyCode.CNY);
2019
});
21-
MoneyContext.DefaultThreadContext = myDefaultContext;
2220

23-
var money = new Money(10.1234m);
21+
// or
22+
//var myDefaultContext = MoneyContext.Create(
23+
// opt =>
24+
// {
25+
// opt.MaxScale = 4;
26+
// opt.DefaultCurrency = CurrencyInfo.FromCode(CurrencyCode.CNY);
27+
// opt.EnforceZeroCurrencyMatching = true;
28+
// });
29+
//MoneyContext.DefaultThreadContext = myDefaultContext;
30+
31+
var money = new Money(10.12345m);
2432
Console.WriteLine(money); // ¥10.1234
2533
}
2634

@@ -48,7 +56,7 @@ public static void Money_Test()
4856
// $15.72
4957

5058
// Split without losing cents
51-
var shares = (total + 0.01m).Split(3);
59+
_ = (total + 0.01m).Split(3);
5260
// [$5.24, $5.24, $5.25]
5361
}
5462

@@ -58,11 +66,11 @@ public static void Parse_Test()
5866

5967
var str = money.ToString("R", CultureInfo.InvariantCulture);
6068
Console.WriteLine(str); // EUR 76543.21
61-
var euro = Money.Parse(str, CultureInfo.InvariantCulture);
69+
_ = Money.Parse(str, CultureInfo.InvariantCulture);
6270

6371
str = money.ToString(CultureInfo.InvariantCulture);
6472
Console.WriteLine(str); // €76,543.21
65-
euro = Money.Parse(str, CultureInfo.InvariantCulture);
73+
_ = Money.Parse(str, CultureInfo.InvariantCulture);
6674
}
6775

6876
#endregion

src/plugins/NodaMoneyTest/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ internal static class Program
77

88
private static void Main()
99
{
10+
MoneyTest.DefaultCurrency_Test();
1011
//MoneyTest.Money_Test();
1112
//MoneyTest.Parse_Test();
1213
//MoneyTest.FastMoney_Test();
13-
MoneyTest.DefaultCurrency_Test();
1414

1515
SerializationTest.Serialize_Test();
1616
}
Lines changed: 125 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,147 @@
11
using NodaMoney;
2+
using System.ComponentModel.DataAnnotations;
3+
using System.Diagnostics.CodeAnalysis;
4+
using System.Globalization;
25
using System.Text.Json;
36

47
namespace NodaMoneyTest;
58

6-
internal static class SerializationTest
9+
public static class SerializationTest
710
{
811

912
#region Constants & Statics
1013

14+
public static void Input_Validation_Test()
15+
{
16+
var input = new MyInput("Jane Doe", 25, new FastMoneyDto { Amount = 49.95m, });
17+
var json = JsonSerializer.Serialize(input);
18+
Console.WriteLine(json);
19+
}
20+
21+
public static void Output_Serialization_Test()
22+
{
23+
var money = new FastMoney(99.99m);
24+
var dto = money.ToDto();
25+
26+
var output = new MyOutput("Alice Smith", 28, dto);
27+
var json = JsonSerializer.Serialize(output);
28+
Console.WriteLine(json);
29+
}
30+
1131
public static void Serialize_Test()
1232
{
1333
var dto = new MyDto("John Doe", 30, new FastMoney(99.99m, "USD"));
1434
var json = JsonSerializer.Serialize(dto);
1535

1636
Console.WriteLine(json);
17-
18-
var deserializedDto = JsonSerializer.Deserialize<MyDto>(json);
37+
_ = JsonSerializer.Deserialize<MyDto>(json);
1938
}
2039

2140
#endregion
2241

2342
}
2443

2544
public record MyDto(string Name, int Age, FastMoney Price);
45+
46+
public record MyInput(string Name, int Age, [AmountValidation("1.00000", "100")] FastMoneyDto Price);
47+
48+
public record MyOutput(string Name, int Age, FastMoneyDto Price);
49+
50+
public static class FastMoneyExtensions
51+
{
52+
53+
#region Constants & Statics
54+
55+
public static FastMoneyDto ToDto(this FastMoney fastMoney)
56+
{
57+
return new FastMoneyDto { Amount = fastMoney.Amount, Currency = fastMoney.Currency.Code };
58+
}
59+
60+
#endregion
61+
62+
}
63+
64+
public class FastMoneyDto : IValidatableObject
65+
{
66+
67+
#region Properties
68+
69+
public decimal Amount { get; init; }
70+
71+
public string Currency { get; init; } = CurrencyCode.CNY;
72+
73+
#endregion
74+
75+
#region IValidatableObject implementations
76+
77+
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
78+
{
79+
var results = new List<ValidationResult>();
80+
81+
//validate AmountValidationAttribute
82+
var context = new ValidationContext(this);
83+
_ = Validator.TryValidateProperty(Amount, context, results);
84+
85+
try
86+
{
87+
_ = CurrencyInfo.FromCode(Currency);
88+
}
89+
catch
90+
{
91+
results.Add(new ValidationResult("Invalid currency code.", [nameof(Currency)]));
92+
}
93+
94+
return results;
95+
}
96+
97+
#endregion
98+
99+
}
100+
101+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
102+
public sealed class AmountValidationAttribute : ValidationAttribute
103+
{
104+
[SuppressMessage("Design", "CA1019:Define accessors for attribute arguments", Justification = "<Pending>")]
105+
public AmountValidationAttribute(string minimum, string maximum)
106+
{
107+
Minimum = decimal.Parse(minimum, CultureInfo.InvariantCulture);
108+
Maximum = decimal.Parse(maximum, CultureInfo.InvariantCulture);
109+
110+
ArgumentOutOfRangeException.ThrowIfLessThan(Minimum, FastMoney.MinValue.Amount);
111+
ArgumentOutOfRangeException.ThrowIfGreaterThan(Maximum, FastMoney.MaxValue.Amount);
112+
113+
if (Minimum.Scale > 4)
114+
{
115+
throw new ArgumentException("Scale cannot be greater than 4.", nameof(minimum));
116+
}
117+
if (Maximum.Scale > 4)
118+
{
119+
throw new ArgumentException("Scale cannot be greater than 4.", nameof(maximum));
120+
}
121+
}
122+
123+
#region Properties
124+
125+
/// <summary>
126+
/// Gets the maximum allowed field value.
127+
/// </summary>
128+
public decimal Maximum { get; }
129+
130+
/// <summary>
131+
/// Specifies whether validation should fail for values that are equal to System.ComponentModel.DataAnnotations.RangeAttribute.Maximum.
132+
/// </summary>
133+
public bool MaximumIsExclusive { get; set; }
134+
135+
/// <summary>
136+
/// Gets the minimum allowed field value.
137+
/// </summary>
138+
public decimal Minimum { get; }
139+
140+
/// <summary>
141+
/// Specifies whether validation should fail for values that are equal to System.ComponentModel.DataAnnotations.RangeAttribute.Minimum.
142+
/// </summary>
143+
public bool MinimumIsExclusive { get; set; }
144+
145+
#endregion
146+
147+
}

0 commit comments

Comments
 (0)