Skip to content

Commit 3e719e5

Browse files
Tino KlijnDotNet2Web
authored andcommitted
IsValid And IsValidAsync Tested
1 parent 4790f65 commit 3e719e5

File tree

2 files changed

+280
-18
lines changed

2 files changed

+280
-18
lines changed
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
using System;
2+
using System.Globalization;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using Bogus;
7+
using CsvCore.Exceptions;
8+
using CsvCore.Reader;
9+
using CsvCore.Specs.Helpers;
10+
using CsvCore.Specs.Models;
11+
using CsvCore.Specs.Models.CsvContent;
12+
using CsvCore.Writer;
13+
using FluentAssertions;
14+
using Xunit;
15+
16+
namespace CsvCore.Specs.Features.Validation;
17+
18+
public class CsvCoreReaderValidationAsyncSpecs
19+
{
20+
private const string CsvExtension = "csv";
21+
private const string ErrorsPath = "Errors";
22+
23+
[Fact]
24+
public async Task Should_Throw_MissingFileException_When_Trying_To_Validate_The_Input_File()
25+
{
26+
// Arrange
27+
var csvCoreReader = new CsvCoreReader();
28+
29+
// Act
30+
var act = async () => await csvCoreReader
31+
.IsValidAsync<PersonModel>(Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension)));
32+
33+
// Assert
34+
await act.Should().ThrowAsync<MissingFileException>();
35+
}
36+
37+
[Fact]
38+
public async Task Should_Validate_The_Input_That_Only_Contains_Valid_Data()
39+
{
40+
// Arrange
41+
var filePath = Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension));
42+
var delimiter = char.Parse(CultureInfo.CurrentCulture.TextInfo.ListSeparator);
43+
44+
var persons = new Faker<CsvContentModel>()
45+
.RuleFor(person => person.Name, (faker, _) => faker.Person.FirstName)
46+
.RuleFor(person => person.Surname, (faker, _) => faker.Person.LastName)
47+
.RuleFor(person => person.BirthDate, (faker, _) => faker.Person.DateOfBirth.ToShortDateString())
48+
.RuleFor(person => person.Email, (faker, _) => faker.Internet.Email())
49+
.Generate(5);
50+
51+
new CsvCoreWriter().UseDelimiter(delimiter).Write(filePath, persons);
52+
53+
var csvCoreReader = new CsvCoreReader();
54+
55+
// Act
56+
var result = await csvCoreReader
57+
.WithoutHeader()
58+
.IsValidAsync<PersonModel>(filePath);
59+
60+
// Assert
61+
result.Should().BeEmpty();
62+
63+
// Cleanup
64+
FileHelper.DeleteTestFile(filePath);
65+
}
66+
67+
[Fact]
68+
public async Task Should_Validate_The_Input_When_A_Date_Cannot_Be_Converted()
69+
{
70+
// Arrange
71+
var filePath = Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension));
72+
73+
var persons = new Faker<CsvContentModel>()
74+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
75+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
76+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
77+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
78+
.Generate(5);
79+
80+
var delimiter = char.Parse(CultureInfo.CurrentCulture.TextInfo.ListSeparator);
81+
82+
var invalid = new Faker<CsvContentModel>()
83+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
84+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
85+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
86+
.Generate();
87+
88+
invalid.BirthDate = "01-01-2023T00:00:00";
89+
90+
persons.Add(invalid);
91+
92+
new CsvCoreWriter().UseDelimiter(delimiter)
93+
.Write(filePath, persons);
94+
95+
var csvCoreReader = new CsvCoreReader();
96+
97+
// Act
98+
var result = await csvCoreReader
99+
.IsValidAsync<PersonModel>(filePath);
100+
101+
// Assert
102+
var resultList = result.ToList();
103+
104+
resultList.Should().NotBeEmpty();
105+
resultList.Count.Should().Be(1);
106+
107+
resultList.First().RowNumber.Should().Be(6);
108+
resultList.First().PropertyName.Should().Be("BirthDate");
109+
resultList.First().ConversionError.Should().Be("Cannot convert '01-01-2023T00:00:00' to System.DateOnly.");
110+
111+
// Cleanup
112+
FileHelper.DeleteTestFile(filePath);
113+
}
114+
115+
[Fact]
116+
public async Task Should_Validate_The_Input_When_Reading_The_Csv_File()
117+
{
118+
// Arrange
119+
var csvCoreReader = new CsvCoreReader();
120+
var delimiter = char.Parse(CultureInfo.CurrentCulture.TextInfo.ListSeparator);
121+
122+
var directory = Directory.GetCurrentDirectory();
123+
var filePath = Path.Combine(directory, new Faker().System.FileName(CsvExtension));
124+
125+
var persons = new Faker<CsvContentModel>()
126+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
127+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
128+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
129+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
130+
.Generate(5);
131+
132+
var invalid1 = new Faker<CsvContentModel>()
133+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
134+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
135+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
136+
.Generate();
137+
138+
invalid1.BirthDate = "01-01-2023T00:00:00";
139+
140+
var invalid2 = new Faker<CsvContentModel>()
141+
.RuleFor(person => person.Name, _ => null)
142+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
143+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
144+
.RuleFor(person => person.Email, _ => null)
145+
.Generate();
146+
147+
var anotherSetValidData = new Faker<CsvContentModel>()
148+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
149+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
150+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
151+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
152+
.Generate(5);
153+
154+
persons.Add(invalid1);
155+
persons.Add(invalid2);
156+
persons.AddRange(anotherSetValidData);
157+
158+
new CsvCoreWriter().UseDelimiter(delimiter).Write(filePath, persons);
159+
160+
// Act
161+
var result = await csvCoreReader
162+
.Validate()
163+
.ReadAsync<PersonModel>(filePath);
164+
165+
// Assert
166+
var resultList = result.ToList();
167+
resultList.Should().NotBeEmpty();
168+
resultList.Count.Should().Be(10);
169+
170+
var errorFile = Path.GetFileNameWithoutExtension(filePath);
171+
var errorFolderPath = Path.Combine(Directory.GetCurrentDirectory(), ErrorsPath);
172+
173+
var errors = await File.ReadAllLinesAsync(Path.Combine(errorFolderPath, $"{errorFile}_errors.csv"));
174+
errors.Should().NotBeNull();
175+
errors.Length.Should().Be(4);
176+
177+
errors[1].Should().Be($"6{delimiter}BirthDate{delimiter}Cannot convert '01-01-2023T00:00:00' to System.DateOnly.");
178+
errors[2].Should().Be($"7{delimiter}Name{delimiter}The value for Name cannot be null or empty.");
179+
errors[3].Should().Be($"7{delimiter}Email{delimiter}The value for Email cannot be null or empty.");
180+
181+
// Cleanup
182+
FileHelper.DeleteTestFile(filePath);
183+
FileHelper.DeleteTestFile(errorFolderPath);
184+
}
185+
186+
[Theory]
187+
[InlineData(" ", false)]
188+
[InlineData("", false)]
189+
[InlineData(null, false)]
190+
[InlineData(" ", true)]
191+
[InlineData("", true)]
192+
[InlineData(null, true)]
193+
public async Task Should_Generate_A_Full_Model_With_Invalid_Records_When_Reading_The_Csv_File_Without_Validation(
194+
string invalidBirthDate, bool withoutHeader)
195+
{
196+
// Arrange
197+
var csvCoreReader = new CsvCoreReader();
198+
var delimiter = char.Parse(CultureInfo.CurrentCulture.TextInfo.ListSeparator);
199+
200+
var directory = Directory.GetCurrentDirectory();
201+
var filePath = Path.Combine(directory, new Faker().System.FileName(CsvExtension));
202+
203+
var persons = new Faker<CsvContentModel>()
204+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
205+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
206+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
207+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
208+
.Generate(5);
209+
210+
var invalid1 = new Faker<CsvContentModel>()
211+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
212+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
213+
.RuleFor(person => person.BirthDate, _ => invalidBirthDate)
214+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
215+
.Generate();
216+
217+
var invalid2 = new Faker<CsvContentModel>()
218+
.RuleFor(person => person.Name, _ => null)
219+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
220+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
221+
.RuleFor(person => person.Email, _ => null)
222+
.Generate();
223+
224+
var anotherSetValidData = new Faker<CsvContentModel>()
225+
.RuleFor(person => person.Name, faker => faker.Person.FirstName)
226+
.RuleFor(person => person.Surname, faker => faker.Person.LastName)
227+
.RuleFor(person => person.BirthDate, faker => faker.Person.DateOfBirth.ToShortDateString())
228+
.RuleFor(person => person.Email, faker => faker.Internet.Email())
229+
.Generate(5);
230+
231+
persons.Add(invalid1);
232+
persons.Add(invalid2);
233+
persons.AddRange(anotherSetValidData);
234+
235+
var csvCoreWriter = new CsvCoreWriter();
236+
237+
if (withoutHeader)
238+
{
239+
csvCoreWriter.WithoutHeader();
240+
}
241+
242+
csvCoreWriter.UseDelimiter(delimiter).Write(filePath, persons);
243+
244+
if (withoutHeader)
245+
{
246+
csvCoreReader.WithoutHeader();
247+
}
248+
249+
// Act
250+
var result = await csvCoreReader
251+
.ReadAsync<PersonModel>(filePath);
252+
253+
// Assert
254+
var resultList = result.ToList();
255+
resultList.Should().NotBeEmpty();
256+
resultList.Count.Should().Be(12);
257+
258+
resultList[5].BirthDate.Should().Be(DateOnly.MinValue);
259+
260+
// Cleanup
261+
FileHelper.DeleteTestFile(filePath);
262+
}
263+
}

CsvCore.Specs/Features/Validation/CsvCoreReaderValidationSpecs.cs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Globalization;
33
using System.IO;
44
using System.Linq;
5-
using System.Threading.Tasks;
65
using Bogus;
76
using CsvCore.Exceptions;
87
using CsvCore.Reader;
@@ -21,21 +20,21 @@ public class CsvCoreReaderValidationSpecs
2120
private const string ErrorsPath = "Errors";
2221

2322
[Fact]
24-
public async Task Should_Throw_MissingFileException_When_Trying_To_Validate_The_Input_File()
23+
public void Should_Throw_MissingFileException_When_Trying_To_Validate_The_Input_File()
2524
{
2625
// Arrange
2726
var csvCoreReader = new CsvCoreReader();
2827

2928
// Act
30-
var act = async () => await csvCoreReader
31-
.IsValidAsync<PersonModel>(Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension)));
29+
var act = () => csvCoreReader
30+
.IsValid<PersonModel>(Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension)));
3231

3332
// Assert
34-
await act.Should().ThrowAsync<MissingFileException>();
33+
act.Should().Throw<MissingFileException>();
3534
}
3635

3736
[Fact]
38-
public async Task Should_Validate_The_Input_That_Only_Contains_Valid_Data()
37+
public void Should_Validate_The_Input_That_Only_Contains_Valid_Data()
3938
{
4039
// Arrange
4140
var filePath = Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension));
@@ -53,9 +52,9 @@ public async Task Should_Validate_The_Input_That_Only_Contains_Valid_Data()
5352
var csvCoreReader = new CsvCoreReader();
5453

5554
// Act
56-
var result = await csvCoreReader
55+
var result = csvCoreReader
5756
.WithoutHeader()
58-
.IsValidAsync<PersonModel>(filePath);
57+
.IsValid<PersonModel>(filePath);
5958

6059
// Assert
6160
result.Should().BeEmpty();
@@ -65,7 +64,7 @@ public async Task Should_Validate_The_Input_That_Only_Contains_Valid_Data()
6564
}
6665

6766
[Fact]
68-
public async Task Should_Validate_The_Input_When_A_Date_Cannot_Be_Converted()
67+
public void Should_Validate_The_Input_When_A_Date_Cannot_Be_Converted()
6968
{
7069
// Arrange
7170
var filePath = Path.Combine(Directory.GetCurrentDirectory(), new Faker().System.FileName(CsvExtension));
@@ -95,8 +94,8 @@ public async Task Should_Validate_The_Input_When_A_Date_Cannot_Be_Converted()
9594
var csvCoreReader = new CsvCoreReader();
9695

9796
// Act
98-
var result = await csvCoreReader
99-
.IsValidAsync<PersonModel>(filePath);
97+
var result = csvCoreReader
98+
.IsValid<PersonModel>(filePath);
10099

101100
// Assert
102101
var resultList = result.ToList();
@@ -113,7 +112,7 @@ public async Task Should_Validate_The_Input_When_A_Date_Cannot_Be_Converted()
113112
}
114113

115114
[Fact]
116-
public async Task Should_Validate_The_Input_When_Reading_The_Csv_File()
115+
public void Should_Validate_The_Input_When_Reading_The_Csv_File()
117116
{
118117
// Arrange
119118
var csvCoreReader = new CsvCoreReader();
@@ -158,9 +157,9 @@ public async Task Should_Validate_The_Input_When_Reading_The_Csv_File()
158157
new CsvCoreWriter().UseDelimiter(delimiter).Write(filePath, persons);
159158

160159
// Act
161-
var result = await csvCoreReader
160+
var result = csvCoreReader
162161
.Validate()
163-
.ReadAsync<PersonModel>(filePath);
162+
.Read<PersonModel>(filePath);
164163

165164
// Assert
166165
var resultList = result.ToList();
@@ -170,7 +169,7 @@ public async Task Should_Validate_The_Input_When_Reading_The_Csv_File()
170169
var errorFile = Path.GetFileNameWithoutExtension(filePath);
171170
var errorFolderPath = Path.Combine(Directory.GetCurrentDirectory(), ErrorsPath);
172171

173-
var errors = await File.ReadAllLinesAsync(Path.Combine(errorFolderPath, $"{errorFile}_errors.csv"));
172+
var errors = File.ReadAllLines(Path.Combine(errorFolderPath, $"{errorFile}_errors.csv"));
174173
errors.Should().NotBeNull();
175174
errors.Length.Should().Be(4);
176175

@@ -190,7 +189,7 @@ public async Task Should_Validate_The_Input_When_Reading_The_Csv_File()
190189
[InlineData(" ", true)]
191190
[InlineData("", true)]
192191
[InlineData(null, true)]
193-
public async Task Should_Generate_A_Full_Model_With_Invalid_Records_When_Reading_The_Csv_File_Without_Validation(
192+
public void Should_Generate_A_Full_Model_With_Invalid_Records_When_Reading_The_Csv_File_Without_Validation(
194193
string invalidBirthDate, bool withoutHeader)
195194
{
196195
// Arrange
@@ -247,8 +246,8 @@ public async Task Should_Generate_A_Full_Model_With_Invalid_Records_When_Reading
247246
}
248247

249248
// Act
250-
var result = await csvCoreReader
251-
.ReadAsync<PersonModel>(filePath);
249+
var result = csvCoreReader
250+
.Read<PersonModel>(filePath);
252251

253252
// Assert
254253
var resultList = result.ToList();

0 commit comments

Comments
 (0)