Skip to content

Commit 638a4b8

Browse files
Merge pull request #657 from PathfinderHonorManager/develop
Added tests and validation for club
2 parents dd89288 + ccc050f commit 638a4b8

File tree

2 files changed

+197
-41
lines changed

2 files changed

+197
-41
lines changed

PathfinderHonorManager.Tests/Service/ClubServiceTests.cs

Lines changed: 185 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
using System.Threading;
44
using System.Threading.Tasks;
55
using AutoMapper;
6+
using FluentValidation;
67
using Microsoft.EntityFrameworkCore;
8+
using Microsoft.Extensions.Logging;
79
using Microsoft.Extensions.Logging.Abstractions;
810
using NUnit.Framework;
911
using PathfinderHonorManager.DataAccess;
@@ -12,54 +14,50 @@
1214
using PathfinderHonorManager.Model;
1315
using PathfinderHonorManager.Service;
1416
using PathfinderHonorManager.Tests.Helpers;
17+
using PathfinderHonorManager.Validators;
18+
using Incoming = PathfinderHonorManager.Dto.Incoming;
1519

1620
namespace PathfinderHonorManager.Tests.Service
1721
{
1822
public class ClubServiceTests
1923
{
24+
protected DbContextOptions<PathfinderContext> ContextOptions { get; }
25+
private ClubService _clubService;
26+
private List<Club> _clubs;
27+
private IValidator<Incoming.ClubDto> _validator;
28+
2029
public ClubServiceTests()
2130
{
2231
ContextOptions = new DbContextOptionsBuilder<PathfinderContext>()
2332
.UseInMemoryDatabase(databaseName: "TestDb")
2433
.Options;
2534
}
2635

27-
protected DbContextOptions<PathfinderContext> ContextOptions { get; }
28-
29-
private ClubService _clubService;
30-
31-
private List<Club> _clubs;
32-
3336
[SetUp]
3437
public async Task SetUp()
3538
{
36-
using (var dbContext = new PathfinderContext(ContextOptions))
37-
{
38-
await SeedDatabase(dbContext);
39-
}
39+
using var dbContext = new PathfinderContext(ContextOptions);
40+
await DatabaseCleaner.CleanDatabase(dbContext);
41+
await SeedDatabase(dbContext);
4042
}
4143

4244
private async Task SeedDatabase(PathfinderContext dbContext)
4345
{
4446
_clubs = new List<Club>
45-
{
46-
new Club
4747
{
48-
ClubID = Guid.NewGuid(),
49-
Name = "Test Club 1"
50-
},
51-
new Club
52-
{
53-
ClubID = Guid.NewGuid(),
54-
Name = "Test Club 2"
55-
},
56-
new Club
57-
{
58-
ClubID = Guid.NewGuid(),
59-
Name = "Test Club 3"
60-
}
61-
};
62-
48+
new Club
49+
{
50+
ClubID = Guid.NewGuid(),
51+
ClubCode = "TESTCLUB1",
52+
Name = "Test Club 1"
53+
},
54+
new Club
55+
{
56+
ClubID = Guid.NewGuid(),
57+
ClubCode = "TESTCLUB2",
58+
Name = "Test Club 2"
59+
}
60+
};
6361

6462
await dbContext.Clubs.AddRangeAsync(_clubs);
6563
await dbContext.SaveChangesAsync();
@@ -70,26 +68,23 @@ public async Task GetAllAsync_ReturnsAllClubs()
7068
{
7169
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperConfig>());
7270
IMapper mapper = mapperConfiguration.CreateMapper();
73-
7471
var logger = new NullLogger<ClubService>();
7572

76-
var validator = new DummyValidator<ClubDto>();
77-
7873
using (var dbContext = new PathfinderContext(ContextOptions))
7974
{
80-
_clubService = new ClubService(dbContext, mapper, logger);
75+
_validator = new ClubValidator(dbContext);
76+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
8177

8278
// Act
8379
CancellationToken token = new();
8480
var result = await _clubService.GetAllAsync(token);
81+
8582
// Assert
8683
Assert.That(result, Is.Not.Null);
8784
Assert.That(result.Count, Is.EqualTo(_clubs.Count));
8885
}
8986
}
9087

91-
// ...
92-
9388
[TestCase(0)]
9489
public async Task GetByIdAsync_ClubExists_ReturnsClub(int clubIndex)
9590
{
@@ -99,7 +94,8 @@ public async Task GetByIdAsync_ClubExists_ReturnsClub(int clubIndex)
9994

10095
using (var dbContext = new PathfinderContext(ContextOptions))
10196
{
102-
_clubService = new ClubService(dbContext, mapper, logger);
97+
_validator = new ClubValidator(dbContext);
98+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
10399

104100
// Act
105101
CancellationToken token = new();
@@ -122,7 +118,8 @@ public async Task GetByIdAsync_ClubDoesNotExist_ReturnsNull()
122118

123119
using (var dbContext = new PathfinderContext(ContextOptions))
124120
{
125-
_clubService = new ClubService(dbContext, mapper, logger);
121+
_validator = new ClubValidator(dbContext);
122+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
126123

127124
// Act
128125
CancellationToken token = new();
@@ -133,17 +130,165 @@ public async Task GetByIdAsync_ClubDoesNotExist_ReturnsNull()
133130
Assert.That(result, Is.Null);
134131
}
135132
}
133+
134+
[TestCase]
135+
public async Task CreateAsync_ValidClub_ReturnsCreatedClub()
136+
{
137+
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperConfig>());
138+
IMapper mapper = mapperConfiguration.CreateMapper();
139+
var logger = new NullLogger<ClubService>();
140+
141+
using (var dbContext = new PathfinderContext(ContextOptions))
142+
{
143+
_validator = new ClubValidator(dbContext);
144+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
145+
146+
// Act
147+
CancellationToken token = new();
148+
var newClub = new Incoming.ClubDto
149+
{
150+
Name = "New Test Club",
151+
ClubCode = "NEWCLUB"
152+
};
153+
154+
var result = await _clubService.CreateAsync(newClub, token);
155+
156+
// Assert
157+
Assert.That(result, Is.Not.Null);
158+
Assert.That(result.Name, Is.EqualTo(newClub.Name));
159+
Assert.That(result.ClubCode, Is.EqualTo(newClub.ClubCode));
160+
Assert.That(result.ClubID, Is.Not.EqualTo(Guid.Empty));
161+
162+
// Verify the club was added to the database
163+
var savedClub = await dbContext.Clubs.SingleOrDefaultAsync(c => c.ClubCode == newClub.ClubCode);
164+
Assert.That(savedClub, Is.Not.Null);
165+
Assert.That(savedClub.Name, Is.EqualTo(newClub.Name));
166+
}
167+
}
168+
169+
[TestCase]
170+
public async Task CreateAsync_DuplicateClubCode_ThrowsValidationException()
171+
{
172+
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperConfig>());
173+
IMapper mapper = mapperConfiguration.CreateMapper();
174+
var logger = new NullLogger<ClubService>();
175+
176+
using (var dbContext = new PathfinderContext(ContextOptions))
177+
{
178+
_validator = new ClubValidator(dbContext);
179+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
180+
181+
// Act
182+
CancellationToken token = new();
183+
var newClub = new Incoming.ClubDto
184+
{
185+
Name = "Duplicate Club",
186+
ClubCode = _clubs[0].ClubCode // Using existing club code to trigger exception
187+
};
188+
189+
// Assert
190+
Assert.ThrowsAsync<ValidationException>(() =>
191+
_clubService.CreateAsync(newClub, token));
192+
}
193+
}
194+
195+
[TestCase(0)]
196+
public async Task UpdateAsync_ValidClub_ReturnsUpdatedClub(int clubIndex)
197+
{
198+
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperConfig>());
199+
IMapper mapper = mapperConfiguration.CreateMapper();
200+
var logger = new NullLogger<ClubService>();
201+
202+
using (var dbContext = new PathfinderContext(ContextOptions))
203+
{
204+
_validator = new ClubValidator(dbContext);
205+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
206+
207+
// Act
208+
CancellationToken token = new();
209+
var clubId = _clubs[clubIndex].ClubID;
210+
var updatedClub = new Incoming.ClubDto
211+
{
212+
Name = "Updated Club Name",
213+
ClubCode = "UPDATED"
214+
};
215+
216+
var result = await _clubService.UpdateAsync(clubId, updatedClub, token);
217+
218+
// Assert
219+
Assert.That(result, Is.Not.Null);
220+
Assert.That(result.ClubID, Is.EqualTo(clubId));
221+
Assert.That(result.Name, Is.EqualTo(updatedClub.Name));
222+
Assert.That(result.ClubCode, Is.EqualTo(updatedClub.ClubCode));
223+
224+
// Verify the club was updated in the database
225+
var savedClub = await dbContext.Clubs.FindAsync(clubId);
226+
Assert.That(savedClub, Is.Not.Null);
227+
Assert.That(savedClub.Name, Is.EqualTo(updatedClub.Name));
228+
Assert.That(savedClub.ClubCode, Is.EqualTo(updatedClub.ClubCode));
229+
}
230+
}
231+
232+
[TestCase]
233+
public async Task UpdateAsync_NonExistentClub_ReturnsNull()
234+
{
235+
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperConfig>());
236+
IMapper mapper = mapperConfiguration.CreateMapper();
237+
var logger = new NullLogger<ClubService>();
238+
239+
using (var dbContext = new PathfinderContext(ContextOptions))
240+
{
241+
_validator = new ClubValidator(dbContext);
242+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
243+
244+
// Act
245+
CancellationToken token = new();
246+
var nonExistentId = Guid.NewGuid();
247+
var updatedClub = new Incoming.ClubDto
248+
{
249+
Name = "Non Existent Club",
250+
ClubCode = "NONEXIST"
251+
};
252+
253+
var result = await _clubService.UpdateAsync(nonExistentId, updatedClub, token);
254+
255+
// Assert
256+
Assert.That(result, Is.Null);
257+
}
258+
}
136259

260+
[TestCase(0)]
261+
public async Task UpdateAsync_DuplicateClubCode_ThrowsValidationException(int clubIndex)
262+
{
263+
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperConfig>());
264+
IMapper mapper = mapperConfiguration.CreateMapper();
265+
var logger = new NullLogger<ClubService>();
266+
267+
using (var dbContext = new PathfinderContext(ContextOptions))
268+
{
269+
_validator = new ClubValidator(dbContext);
270+
_clubService = new ClubService(dbContext, mapper, logger, _validator);
271+
272+
// Act
273+
CancellationToken token = new();
274+
var clubId = _clubs[clubIndex].ClubID;
275+
var updatedClub = new Incoming.ClubDto
276+
{
277+
Name = "Updated Club Name",
278+
ClubCode = _clubs[1].ClubCode // Using another club's code to trigger duplicate exception
279+
};
280+
281+
// Assert
282+
Assert.ThrowsAsync<ValidationException>(() =>
283+
_clubService.UpdateAsync(clubId, updatedClub, token));
284+
}
285+
}
137286

138287
[TearDown]
139288
public async Task TearDown()
140289
{
141290
using var dbContext = new PathfinderContext(ContextOptions);
142-
143-
dbContext.Clubs.RemoveRange();
144-
145-
await dbContext.SaveChangesAsync();
291+
await DatabaseCleaner.CleanDatabase(dbContext);
146292
}
147293
}
148-
149294
}

PathfinderHonorManager/Service/ClubService.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@ public class ClubService : IClubService
2323

2424
private readonly ILogger _logger;
2525

26+
private readonly IValidator<Incoming.ClubDto> _validator;
27+
2628
public ClubService(
2729
PathfinderContext context,
2830
IMapper mapper,
29-
ILogger<ClubService> logger)
31+
ILogger<ClubService> logger,
32+
IValidator<Incoming.ClubDto> validator)
3033
{
3134
_dbContext = context;
3235
_mapper = mapper;
3336
_logger = logger;
37+
_validator = validator;
3438
}
3539

3640
public async Task<ICollection<Outgoing.ClubDto>> GetAllAsync(CancellationToken token)
@@ -88,6 +92,8 @@ public ClubService(
8892

8993
try
9094
{
95+
await _validator.ValidateAsync(club, options => options.ThrowOnFailures().IncludeRuleSets("post"), token);
96+
9197
var entity = _mapper.Map<Club>(club);
9298
await _dbContext.Clubs.AddAsync(entity, token);
9399
await _dbContext.SaveChangesAsync(token);
@@ -117,6 +123,11 @@ public ClubService(
117123
return default;
118124
}
119125

126+
if (entity.ClubCode != club.ClubCode)
127+
{
128+
await _validator.ValidateAsync(club, options => options.ThrowOnFailures().IncludeRuleSets("post"), token);
129+
}
130+
120131
_mapper.Map(club, entity);
121132
await _dbContext.SaveChangesAsync(token);
122133

0 commit comments

Comments
 (0)