academia/tests/Domain.Tests/Services/EnrollmentDomainServiceTest...

126 lines
4.1 KiB
C#

namespace Domain.Tests.Services;
using Domain.Entities;
using Domain.Exceptions;
using Domain.Services;
using Domain.ValueObjects;
using FluentAssertions;
using Xunit;
public class EnrollmentDomainServiceTests
{
private readonly EnrollmentDomainService _sut = new();
private static Email ValidEmail => Email.Create("test@example.com");
[Fact]
public void ValidateEnrollment_WhenValid_ShouldNotThrow()
{
var student = new Student("John Doe", ValidEmail);
var subject = new Subject("Math", professorId: 1);
var act = () => _sut.ValidateEnrollment(student, subject);
act.Should().NotThrow();
}
[Fact]
public void ValidateEnrollment_WhenMaxEnrollmentsReached_ShouldThrow()
{
var student = new Student("John Doe", ValidEmail);
AddEnrollmentsWithDifferentProfessors(student, 3);
var subject = new Subject("Physics", professorId: 99);
var act = () => _sut.ValidateEnrollment(student, subject);
act.Should().Throw<MaxEnrollmentsExceededException>()
.Which.Code.Should().Be("MAX_ENROLLMENTS");
}
[Fact]
public void ValidateEnrollment_WhenSameProfessor_ShouldThrow()
{
var student = new Student("John Doe", ValidEmail);
var existingSubject = new Subject("Math", professorId: 1);
AddEnrollmentWithSubject(student, existingSubject);
var newSubject = new Subject("Algebra", professorId: 1);
var act = () => _sut.ValidateEnrollment(student, newSubject);
act.Should().Throw<SameProfessorConstraintException>()
.Which.Code.Should().Be("SAME_PROFESSOR");
}
[Fact]
public void ValidateEnrollment_WhenDuplicateSubject_ShouldThrow()
{
var student = new Student("John Doe", ValidEmail);
var subject = new Subject("Math", professorId: 1);
SetSubjectId(subject, 10);
AddEnrollmentWithSubject(student, subject);
// Same subject ID but different professor to bypass professor check
var duplicateSubject = new Subject("Math", professorId: 2);
SetSubjectId(duplicateSubject, 10);
var act = () => _sut.ValidateEnrollment(student, duplicateSubject);
act.Should().Throw<DuplicateEnrollmentException>()
.Which.Code.Should().Be("DUPLICATE_ENROLLMENT");
}
[Fact]
public void CreateEnrollment_WhenValid_ShouldCreateAndAddToStudent()
{
var student = new Student("John Doe", ValidEmail);
var subject = new Subject("Math", professorId: 1);
var enrollment = _sut.CreateEnrollment(student, subject);
enrollment.Should().NotBeNull();
student.Enrollments.Should().Contain(enrollment);
enrollment.StudentId.Should().Be(student.Id);
enrollment.SubjectId.Should().Be(subject.Id);
}
[Fact]
public void CreateEnrollment_WhenInvalid_ShouldNotAddToStudent()
{
var student = new Student("John Doe", ValidEmail);
AddEnrollmentsWithDifferentProfessors(student, 3);
var subject = new Subject("Physics", professorId: 99);
var act = () => _sut.CreateEnrollment(student, subject);
act.Should().Throw<MaxEnrollmentsExceededException>();
student.Enrollments.Should().HaveCount(3);
}
private static void AddEnrollmentsWithDifferentProfessors(Student student, int count)
{
for (int i = 0; i < count; i++)
{
var subject = new Subject($"Subject{i}", professorId: i + 1);
SetSubjectId(subject, i + 1);
AddEnrollmentWithSubject(student, subject);
}
}
private static void AddEnrollmentWithSubject(Student student, Subject subject)
{
var enrollment = new Enrollment(student.Id, subject.Id);
SetSubjectOnEnrollment(enrollment, subject);
student.AddEnrollment(enrollment);
}
private static void SetSubjectOnEnrollment(Enrollment enrollment, Subject subject)
{
typeof(Enrollment).GetProperty("Subject")!.SetValue(enrollment, subject);
}
private static void SetSubjectId(Subject subject, int id)
{
typeof(Subject).GetProperty("Id")!.SetValue(subject, id);
}
}