Skip to content

Commit 2c22f9a

Browse files
authored
Merge pull request #13 from VelkoTgr6/development
Development
2 parents 32d5ecd + 94aa85b commit 2c22f9a

File tree

11 files changed

+205
-299
lines changed

11 files changed

+205
-299
lines changed

StudentManagementSystem.Core/Services/Admin/AdminStudentService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ public async Task EditRemarkAsync(int remarkId, StudentRemarkFormViewModel model
443443
if (remark == null)
444444
{
445445
logger.LogWarning($"Attempted to edit a non-existing remark with ID: {remarkId} .");
446-
throw new ArgumentException($"Remark with ID: {remarkId} not found.");
446+
throw new KeyNotFoundException($"Remark with ID: {remarkId} not found.");
447447
}
448448

449449
remark.RemarkText = model.RemarkText;
@@ -469,7 +469,7 @@ public async Task<StudentRemarkFormViewModel> GetRemarkFormModelByIdAsync(int id
469469

470470
if (remark == null)
471471
{
472-
throw new ArgumentException($"Remark with ID: {id} not found.");
472+
throw new KeyNotFoundException($"Remark with ID: {id} not found.");
473473
}
474474

475475
return remark;

StudentManagementSystem.Core/Services/TeacherService.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public async Task<int> AddAbsenceToStudentAsync(AbsenceFormViewModel model, int
271271
{
272272
StudentId = studentId,
273273
CourseId = model.CourseId,
274-
Date = DateTime.SpecifyKind(model.AbsenceDate.Date, DateTimeKind.Utc)
274+
Date = DateTime.SpecifyKind(model.AbsenceDate, DateTimeKind.Utc)
275275
};
276276

277277
student.Аbsences.Add(absence);
@@ -410,7 +410,6 @@ public async Task<GradeFormModel> GetGradeByIdAsync(int gradeId)
410410
StudentId = g.StudentId,
411411
CourseId = g.CourseId,
412412
GradeScore = g.GradeScore,
413-
414413
GradeType = g.GradeType,
415414
SelectedCourseId = g.CourseId,
416415
SelectedGrade = g.GradeScore.ToString(),
@@ -483,14 +482,14 @@ public async Task DeleteGradeAsync(int gradeId)
483482

484483
public async Task<AbsenceFormViewModel> GetAbsenceByIdAsync(int absenceId)
485484
{
486-
var absence =await repository.All<Absence>()
485+
var absence =await repository.AllAsReadOnly<Absence>()
487486
.Where(a => a.Id == absenceId && !a.IsDeleted)
488487
.Select(a=> new AbsenceFormViewModel
489488
{
490489
Id = absenceId,
491490
StudentId = a.StudentId,
492491
CourseId = a.CourseId,
493-
AbsenceDate = a.Date.Date
492+
AbsenceDate = a.Date
494493
})
495494
.FirstOrDefaultAsync();
496495

@@ -514,7 +513,7 @@ public async Task<int> EditAbsenceAsync(int absenceId, AbsenceFormViewModel mode
514513
}
515514

516515
// Ensure DateTime written to Postgres has Kind=Utc
517-
absence.Date = DateTime.SpecifyKind(model.AbsenceDate.Date, DateTimeKind.Utc);
516+
absence.Date = DateTime.SpecifyKind(model.AbsenceDate, DateTimeKind.Utc);
518517
absence.CourseId = model.CourseId;
519518

520519
await repository.SaveChangesAsync();

StudentServiceTests/Admin/AdminClassServiceTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public async Task CreateClassAsync_ShouldAddClass_WhenCalled()
9090

9191
mockRepository.Setup(r => r.AddAsync(It.IsAny<Class>())).Returns(Task.CompletedTask);
9292

93+
var emptyClasses = new List<Class>().AsQueryable().BuildMock();
94+
mockRepository.Setup(r => r.AllAsReadOnly<Class>()).Returns(emptyClasses);
9395

9496
var result = await adminClassService.CreateClassAsync(model);
9597

StudentServiceTests/Admin/AdminCourseServiceTests.cs

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
using MockQueryable;
1+
using Microsoft.Extensions.Logging;
2+
using MockQueryable;
23
using Moq;
3-
using Microsoft.Extensions.Logging;
44
using StudentManagementSystem.Core.Models.Admin.Course;
5+
using StudentManagementSystem.Core.Services;
56
using StudentManagementSystem.Core.Services.Admin;
67
using StudentManagementSystem.Infrastructure.Data.Common;
78
using StudentManagementSystem.Infrastructure.Data.Models;
@@ -82,19 +83,15 @@ public async Task CourseExistAsync_ShouldReturnTrue_WhenCourseExists()
8283
}
8384

8485
[Test]
85-
public async Task CourseExistAsync_ShouldReturnFalse_WhenCourseDoesNotExist()
86+
public void CourseExistAsync_ShouldThrowKeyNotFoundException_WhenCourseDoesNotExist()
8687
{
87-
8888
mockRepository.Setup(repo => repo.AllAsReadOnly<Course>()).Returns(new List<Course>
8989
{
9090
new Course { Id = 1, Name = "Math 101", IsDeleted = false }
9191
}.AsQueryable().BuildMock());
9292

93-
94-
var result = await courseService.CourseExistAsync(99);
95-
96-
97-
Assert.IsFalse(result);
93+
var ex = Assert.ThrowsAsync<KeyNotFoundException>(async () => await courseService.CourseExistAsync(99));
94+
Assert.That(ex.Message, Is.EqualTo("Course with ID: 99 not found"));
9895
}
9996

10097
[Test]
@@ -114,10 +111,10 @@ public async Task CreateCourseAsync_ShouldReturnCourseId_WhenCourseIsCreated()
114111
mockRepository.Setup(repo => repo.AddAsync(It.IsAny<Course>())).Callback<Course>(c => c.Id = newCourseId).Returns(Task.CompletedTask);
115112
mockRepository.Setup(repo => repo.SaveChangesAsync()).ReturnsAsync(1);
116113

114+
mockRepository.Setup(repo => repo.AllAsReadOnly<Course>()).Returns(new List<Course>().AsQueryable().BuildMock());
117115

118116
var result = await courseService.CreateCourseAsync(courseForm, publisherId);
119117

120-
121118
Assert.That(result, Is.EqualTo(newCourseId));
122119
mockRepository.Verify(repo => repo.AddAsync(It.Is<Course>(c =>
123120
c.Name == courseForm.Name &&
@@ -168,19 +165,19 @@ public async Task GetCourseDetailsModelByIdAsync_ShouldReturnCourseDetailsViewMo
168165
}
169166

170167
[Test]
171-
public async Task GetCourseDetailsModelByIdAsync_ShouldThrowArgumentException_WhenCourseDoesNotExist()
168+
public void GetCourseDetailsModelByIdAsync_ShouldThrowKeyNotFoundException_WhenCourseDoesNotExist()
172169
{
173170

174171
mockRepository.Setup(repo => repo.AllAsReadOnly<Course>())
175172
.Returns(new List<Course>().AsQueryable().BuildMock());
176173

177174

178-
var exception = Assert.ThrowsAsync<ArgumentException>(() => courseService.GetCourseDetailsModelByIdAsync(99));
175+
var exception = Assert.ThrowsAsync<KeyNotFoundException>(() => courseService.GetCourseDetailsModelByIdAsync(99));
179176
Assert.That(exception.Message, Is.EqualTo("Course with ID 99 not found."));
180177
}
181178

182179
[Test]
183-
public async Task GetCourseDetailsModelByIdAsync_ShouldThrowArgumentException_WhenCourseIsDeleted()
180+
public void GetCourseDetailsModelByIdAsync_ShouldThrowKeyNotFoundException_WhenCourseIsDeleted()
184181
{
185182

186183
var course = new Course
@@ -201,11 +198,10 @@ public async Task GetCourseDetailsModelByIdAsync_ShouldThrowArgumentException_Wh
201198
.Returns(new List<Course> { course }.AsQueryable().BuildMock());
202199

203200

204-
var exception = Assert.ThrowsAsync<ArgumentException>(() => courseService.GetCourseDetailsModelByIdAsync(1));
201+
var exception = Assert.ThrowsAsync<KeyNotFoundException>(() => courseService.GetCourseDetailsModelByIdAsync(1));
205202
Assert.That(exception.Message, Is.EqualTo("Course with ID 1 not found."));
206203
}
207204

208-
209205
[Test]
210206
public async Task DeleteCourseAsync_ShouldSetCourseToDeleted_WhenCourseExistsAndNotDeleted()
211207
{
@@ -222,22 +218,6 @@ public async Task DeleteCourseAsync_ShouldSetCourseToDeleted_WhenCourseExistsAnd
222218
mockRepository.Verify(repo => repo.SaveChangesAsync(), Times.Once);
223219
}
224220

225-
[Test]
226-
public async Task DeleteCourseAsync_ShouldNotChangeCourse_WhenCourseAlreadyDeleted()
227-
{
228-
229-
var course = new Course { Id = 1, Name = "Math 101", IsDeleted = true };
230-
mockRepository.Setup(repo => repo.GetByIdAsync<Course>(1)).ReturnsAsync(course);
231-
mockRepository.Setup(repo => repo.SaveChangesAsync()).ReturnsAsync(1);
232-
233-
234-
await courseService.DeleteCourseAsync(1);
235-
236-
237-
Assert.IsTrue(course.IsDeleted);
238-
mockRepository.Verify(repo => repo.SaveChangesAsync(), Times.Once);
239-
}
240-
241221
[Test]
242222
public async Task EditCourseAsync_ShouldUpdateCourse_WhenCourseExistsAndNotDeleted()
243223
{
@@ -266,7 +246,7 @@ public async Task EditCourseAsync_ShouldUpdateCourse_WhenCourseExistsAndNotDelet
266246
}
267247

268248
[Test]
269-
public async Task EditCourseAsync_ShouldNotUpdateCourse_WhenCourseIsDeleted()
249+
public void EditCourseAsync_ShouldThrowKeyNotFoundException_WhenCourseIsDeleted()
270250
{
271251

272252
var course = new Course { Id = 1, Name = "Math 101", Description = "Old Description", IsDeleted = true };
@@ -282,12 +262,8 @@ public async Task EditCourseAsync_ShouldNotUpdateCourse_WhenCourseIsDeleted()
282262
mockRepository.Setup(repo => repo.SaveChangesAsync()).ReturnsAsync(1);
283263

284264

285-
await courseService.EditCourseAsync(1, model, publisherId);
286-
287-
288-
Assert.That(course.Name, Is.EqualTo("Math 101"));
289-
Assert.That(course.Description, Is.EqualTo("Old Description"));
290-
mockRepository.Verify(repo => repo.SaveChangesAsync(), Times.Once);
265+
var ex = Assert.ThrowsAsync<KeyNotFoundException>(async () => await courseService.EditCourseAsync(1, model, publisherId));
266+
Assert.That(ex.Message, Is.EqualTo("Course with ID 1 not found."));
291267
}
292268

293269
[Test]
@@ -350,13 +326,13 @@ public async Task GetCourseByIdAsync_ShouldReturnCourse_WhenCourseExists()
350326
}
351327

352328
[Test]
353-
public async Task GetCourseByIdAsync_ShouldThrowException_WhenCourseDoesNotExist()
329+
public void GetCourseByIdAsync_ShouldThrowKeyNotFoundException_WhenCourseDoesNotExist()
354330
{
355331

356332
mockRepository.Setup(repo => repo.GetByIdAsync<CourseServiceModel>(99)).ReturnsAsync((CourseServiceModel)null);
357333

358334

359-
var exception = Assert.ThrowsAsync<ArgumentException>(() => courseService.GetCourseByIdAsync(99));
335+
var exception = Assert.ThrowsAsync<KeyNotFoundException>(() => courseService.GetCourseByIdAsync(99));
360336
Assert.That(exception.Message, Is.EqualTo("Course with ID 99 not found."));
361337
}
362338

@@ -394,19 +370,19 @@ public async Task GetCourseFormModelByIdAsync_ShouldReturnCourseFormViewModel_Wh
394370
}
395371

396372
[Test]
397-
public async Task GetCourseFormModelByIdAsync_ShouldThrowArgumentException_WhenCourseDoesNotExist()
373+
public void GetCourseFormModelByIdAsync_ShouldThrowKeyNotFoundException_WhenCourseDoesNotExist()
398374
{
399375

400376
mockRepository.Setup(repo => repo.AllAsReadOnly<Course>())
401377
.Returns(new List<Course>().AsQueryable().BuildMock());
402378

403379

404-
var exception = Assert.ThrowsAsync<ArgumentException>(() => courseService.GetCourseFormModelByIdAsync(99));
380+
var exception = Assert.ThrowsAsync<KeyNotFoundException>(() => courseService.GetCourseFormModelByIdAsync(99));
405381
Assert.AreEqual("Course with ID 99 not found.", exception.Message);
406382
}
407383

408384
[Test]
409-
public async Task GetCourseFormModelByIdAsync_ShouldThrowArgumentException_WhenCourseIsDeleted()
385+
public void GetCourseFormModelByIdAsync_ShouldThrowKeyNotFoundException_WhenCourseIsDeleted()
410386
{
411387

412388
var course = new Course
@@ -422,7 +398,7 @@ public async Task GetCourseFormModelByIdAsync_ShouldThrowArgumentException_WhenC
422398
.Returns(new List<Course> { course }.AsQueryable().BuildMock());
423399

424400

425-
var exception = Assert.ThrowsAsync<ArgumentException>(() => courseService.GetCourseFormModelByIdAsync(1));
401+
var exception = Assert.ThrowsAsync<KeyNotFoundException>(() => courseService.GetCourseFormModelByIdAsync(1));
426402
Assert.That(exception.Message, Is.EqualTo("Course with ID 1 not found."));
427403
}
428404

StudentServiceTests/Admin/AdminScheduleServiceTests.cs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ public async Task AddCourseScheduleAsync_ShouldAddCourseSchedule_WhenValidModelP
104104
mockRepository.Setup(repo => repo.AddAsync(It.IsAny<CourseSchedule>())).Returns(Task.CompletedTask);
105105
mockRepository.Setup(repo => repo.SaveChangesAsync()).ReturnsAsync(1);
106106

107+
// Ensure AllAsReadOnly returns an IQueryable with an async provider for EF Core async extensions
108+
mockRepository.Setup(repo => repo.AllAsReadOnly<CourseSchedule>())
109+
.Returns(Enumerable.Empty<CourseSchedule>().AsQueryable().BuildMock());
110+
107111

108112
await adminScheduleService.AddCourseScheduleAsync(model);
109113

@@ -139,20 +143,6 @@ public async Task DeleteCourseScheduleAsync_ShouldDeleteSchedule_WhenScheduleExi
139143
mockRepository.Verify(repo => repo.SaveChangesAsync(), Times.Once);
140144
}
141145

142-
[Test]
143-
public async Task DeleteCourseScheduleAsync_ShouldDoNothing_WhenScheduleDoesNotExist()
144-
{
145-
146-
mockRepository.Setup(repo => repo.GetByIdAsync<CourseSchedule>(1))
147-
.ReturnsAsync((CourseSchedule)null);
148-
149-
150-
await adminScheduleService.DeleteCourseScheduleAsync(1);
151-
152-
153-
mockRepository.Verify(repo => repo.DeleteSchedule(It.IsAny<CourseSchedule>()), Times.Never);
154-
mockRepository.Verify(repo => repo.SaveChangesAsync(), Times.Never);
155-
}
156146
[Test]
157147
public async Task EditCourseScheduleAsync_ShouldUpdateSchedule_WhenValidModelProvided()
158148
{
@@ -235,12 +225,11 @@ public async Task GetCourseScheduleByIdAsync_ShouldReturnCourseSchedule_WhenSche
235225
[Test]
236226
public async Task GetCourseScheduleByIdAsync_ShouldThrowException_WhenScheduleDoesNotExist()
237227
{
238-
239228
mockRepository.Setup(repo => repo.AllAsReadOnly<CourseSchedule>())
240229
.Returns(Enumerable.Empty<CourseSchedule>().AsQueryable().BuildMock());
241230

242-
var exception = Assert.ThrowsAsync<Exception>(() => adminScheduleService.GetCourseScheduleByIdAsync(99));
243-
Assert.That(exception.Message, Is.EqualTo("Course schedule not found"));
231+
var exception = Assert.ThrowsAsync<KeyNotFoundException>(() => adminScheduleService.GetCourseScheduleByIdAsync(99));
232+
Assert.That(exception.Message, Is.EqualTo("Course schedule with ID: 99 not found."));
244233
}
245234

246235
}

0 commit comments

Comments
 (0)