From 193a2078b35bf0ed2f7846b5687fb2a02e5b05da Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 13:26:22 +0000
Subject: [PATCH 1/3] Initial plan
From 97468c42336a194cf16b7ecc03040b7bb39ab5a1 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 13:38:15 +0000
Subject: [PATCH 2/3] Add comprehensive unit tests for add course feature
Co-authored-by: Hemavathi15sg <224925058+Hemavathi15sg@users.noreply.github.com>
---
.../CourseRegistration.API.Tests.csproj | 30 ++
api/CourseRegistration.API.Tests/UnitTest1.cs | 10 +
...ourseRegistration.Application.Tests.csproj | 29 ++
.../Services/CourseServiceTests.cs | 271 ++++++++++++++++++
.../CreateCourseDtoValidatorTests.cs | 129 +++++++++
api/CourseRegistration.sln | 28 ++
6 files changed, 497 insertions(+)
create mode 100644 api/CourseRegistration.API.Tests/CourseRegistration.API.Tests.csproj
create mode 100644 api/CourseRegistration.API.Tests/UnitTest1.cs
create mode 100644 api/CourseRegistration.Application.Tests/CourseRegistration.Application.Tests.csproj
create mode 100644 api/CourseRegistration.Application.Tests/Services/CourseServiceTests.cs
create mode 100644 api/CourseRegistration.Application.Tests/Validators/CreateCourseDtoValidatorTests.cs
diff --git a/api/CourseRegistration.API.Tests/CourseRegistration.API.Tests.csproj b/api/CourseRegistration.API.Tests/CourseRegistration.API.Tests.csproj
new file mode 100644
index 0000000..2dfae8b
--- /dev/null
+++ b/api/CourseRegistration.API.Tests/CourseRegistration.API.Tests.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net10.0
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/CourseRegistration.API.Tests/UnitTest1.cs b/api/CourseRegistration.API.Tests/UnitTest1.cs
new file mode 100644
index 0000000..0d806f1
--- /dev/null
+++ b/api/CourseRegistration.API.Tests/UnitTest1.cs
@@ -0,0 +1,10 @@
+namespace CourseRegistration.API.Tests;
+
+public class UnitTest1
+{
+ [Fact]
+ public void Test1()
+ {
+
+ }
+}
diff --git a/api/CourseRegistration.Application.Tests/CourseRegistration.Application.Tests.csproj b/api/CourseRegistration.Application.Tests/CourseRegistration.Application.Tests.csproj
new file mode 100644
index 0000000..57fabec
--- /dev/null
+++ b/api/CourseRegistration.Application.Tests/CourseRegistration.Application.Tests.csproj
@@ -0,0 +1,29 @@
+
+
+
+ net10.0
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/api/CourseRegistration.Application.Tests/Services/CourseServiceTests.cs b/api/CourseRegistration.Application.Tests/Services/CourseServiceTests.cs
new file mode 100644
index 0000000..cc8a84c
--- /dev/null
+++ b/api/CourseRegistration.Application.Tests/Services/CourseServiceTests.cs
@@ -0,0 +1,271 @@
+using AutoMapper;
+using CourseRegistration.Application.DTOs;
+using CourseRegistration.Application.Services;
+using CourseRegistration.Domain.Entities;
+using CourseRegistration.Domain.Interfaces;
+using FluentAssertions;
+using Moq;
+using Xunit;
+
+namespace CourseRegistration.Application.Tests.Services;
+
+///
+/// Unit tests for CourseService focusing on CreateCourseAsync functionality
+///
+public class CourseServiceTests
+{
+ private readonly Mock _mockUnitOfWork;
+ private readonly Mock _mockMapper;
+ private readonly Mock _mockCourseRepository;
+ private readonly CourseService _courseService;
+
+ public CourseServiceTests()
+ {
+ _mockUnitOfWork = new Mock();
+ _mockMapper = new Mock();
+ _mockCourseRepository = new Mock();
+
+ _mockUnitOfWork.Setup(u => u.Courses).Returns(_mockCourseRepository.Object);
+
+ _courseService = new CourseService(_mockUnitOfWork.Object, _mockMapper.Object);
+ }
+
+ [Fact]
+ public async Task CreateCourseAsync_WithValidData_ShouldCreateCourse()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Introduction to C#",
+ Description = "Learn the fundamentals of C# programming",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(10),
+ EndDate = DateTime.UtcNow.AddDays(40),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ var course = new Course
+ {
+ CourseId = Guid.NewGuid(),
+ CourseName = createCourseDto.CourseName,
+ Description = createCourseDto.Description,
+ InstructorName = createCourseDto.InstructorName,
+ StartDate = createCourseDto.StartDate,
+ EndDate = createCourseDto.EndDate,
+ Schedule = createCourseDto.Schedule
+ };
+
+ var courseDto = new CourseDto
+ {
+ CourseId = course.CourseId,
+ CourseName = course.CourseName,
+ Description = course.Description,
+ InstructorName = course.InstructorName,
+ StartDate = course.StartDate,
+ EndDate = course.EndDate,
+ Schedule = course.Schedule
+ };
+
+ _mockMapper.Setup(m => m.Map(It.IsAny())).Returns(course);
+ _mockMapper.Setup(m => m.Map(It.IsAny())).Returns(courseDto);
+ _mockCourseRepository.Setup(r => r.AddAsync(It.IsAny())).ReturnsAsync(course);
+ _mockUnitOfWork.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
+
+ // Act
+ var result = await _courseService.CreateCourseAsync(createCourseDto);
+
+ // Assert
+ result.Should().NotBeNull();
+ result.CourseName.Should().Be(createCourseDto.CourseName);
+ result.Description.Should().Be(createCourseDto.Description);
+ result.InstructorName.Should().Be(createCourseDto.InstructorName);
+ result.StartDate.Should().Be(createCourseDto.StartDate);
+ result.EndDate.Should().Be(createCourseDto.EndDate);
+ result.Schedule.Should().Be(createCourseDto.Schedule);
+
+ _mockCourseRepository.Verify(r => r.AddAsync(It.IsAny()), Times.Once);
+ _mockUnitOfWork.Verify(u => u.SaveChangesAsync(), Times.Once);
+ }
+
+ [Fact]
+ public async Task CreateCourseAsync_WithStartDateInPast_ShouldThrowInvalidOperationException()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Introduction to C#",
+ Description = "Learn the fundamentals of C# programming",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(-5), // Past date
+ EndDate = DateTime.UtcNow.AddDays(30),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(
+ () => _courseService.CreateCourseAsync(createCourseDto));
+
+ exception.Message.Should().Contain("must be in the future");
+
+ _mockCourseRepository.Verify(r => r.AddAsync(It.IsAny()), Times.Never);
+ _mockUnitOfWork.Verify(u => u.SaveChangesAsync(), Times.Never);
+ }
+
+ [Fact]
+ public async Task CreateCourseAsync_WithEndDateBeforeStartDate_ShouldThrowInvalidOperationException()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Introduction to C#",
+ Description = "Learn the fundamentals of C# programming",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(30),
+ EndDate = DateTime.UtcNow.AddDays(10), // Before start date
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(
+ () => _courseService.CreateCourseAsync(createCourseDto));
+
+ exception.Message.Should().Contain("must be after start date");
+
+ _mockCourseRepository.Verify(r => r.AddAsync(It.IsAny()), Times.Never);
+ _mockUnitOfWork.Verify(u => u.SaveChangesAsync(), Times.Never);
+ }
+
+ [Fact]
+ public async Task CreateCourseAsync_WithEndDateEqualToStartDate_ShouldThrowInvalidOperationException()
+ {
+ // Arrange
+ var startDate = DateTime.UtcNow.AddDays(10);
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Introduction to C#",
+ Description = "Learn the fundamentals of C# programming",
+ InstructorName = "John Doe",
+ StartDate = startDate,
+ EndDate = startDate, // Same as start date
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act & Assert
+ var exception = await Assert.ThrowsAsync(
+ () => _courseService.CreateCourseAsync(createCourseDto));
+
+ exception.Message.Should().Contain("must be after start date");
+
+ _mockCourseRepository.Verify(r => r.AddAsync(It.IsAny()), Times.Never);
+ _mockUnitOfWork.Verify(u => u.SaveChangesAsync(), Times.Never);
+ }
+
+ [Fact]
+ public async Task CreateCourseAsync_WithMinimalData_ShouldCreateCourse()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Short Course",
+ Description = null, // Optional field
+ InstructorName = "Jane Smith",
+ StartDate = DateTime.UtcNow.AddDays(7),
+ EndDate = DateTime.UtcNow.AddDays(14),
+ Schedule = "TTh 14:00-15:30"
+ };
+
+ var course = new Course
+ {
+ CourseId = Guid.NewGuid(),
+ CourseName = createCourseDto.CourseName,
+ Description = createCourseDto.Description,
+ InstructorName = createCourseDto.InstructorName,
+ StartDate = createCourseDto.StartDate,
+ EndDate = createCourseDto.EndDate,
+ Schedule = createCourseDto.Schedule
+ };
+
+ var courseDto = new CourseDto
+ {
+ CourseId = course.CourseId,
+ CourseName = course.CourseName,
+ Description = course.Description,
+ InstructorName = course.InstructorName,
+ StartDate = course.StartDate,
+ EndDate = course.EndDate,
+ Schedule = course.Schedule
+ };
+
+ _mockMapper.Setup(m => m.Map(It.IsAny())).Returns(course);
+ _mockMapper.Setup(m => m.Map(It.IsAny())).Returns(courseDto);
+ _mockCourseRepository.Setup(r => r.AddAsync(It.IsAny())).ReturnsAsync(course);
+ _mockUnitOfWork.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
+
+ // Act
+ var result = await _courseService.CreateCourseAsync(createCourseDto);
+
+ // Assert
+ result.Should().NotBeNull();
+ result.CourseName.Should().Be(createCourseDto.CourseName);
+ result.Description.Should().BeNull();
+
+ _mockCourseRepository.Verify(r => r.AddAsync(It.IsAny()), Times.Once);
+ _mockUnitOfWork.Verify(u => u.SaveChangesAsync(), Times.Once);
+ }
+
+ [Fact]
+ public async Task CreateCourseAsync_ShouldGenerateNewCourseId()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Advanced C#",
+ Description = "Deep dive into C# features",
+ InstructorName = "Dr. Smith",
+ StartDate = DateTime.UtcNow.AddDays(15),
+ EndDate = DateTime.UtcNow.AddDays(60),
+ Schedule = "MWF 13:00-14:30"
+ };
+
+ var capturedCourse = (Course?)null;
+
+ _mockMapper.Setup(m => m.Map(It.IsAny()))
+ .Returns((CreateCourseDto dto) => new Course
+ {
+ CourseId = Guid.NewGuid(),
+ CourseName = dto.CourseName,
+ Description = dto.Description,
+ InstructorName = dto.InstructorName,
+ StartDate = dto.StartDate,
+ EndDate = dto.EndDate,
+ Schedule = dto.Schedule
+ });
+
+ _mockCourseRepository.Setup(r => r.AddAsync(It.IsAny()))
+ .Callback(c => capturedCourse = c)
+ .ReturnsAsync((Course c) => c);
+
+ _mockMapper.Setup(m => m.Map(It.IsAny()))
+ .Returns((Course c) => new CourseDto
+ {
+ CourseId = c.CourseId,
+ CourseName = c.CourseName,
+ Description = c.Description,
+ InstructorName = c.InstructorName,
+ StartDate = c.StartDate,
+ EndDate = c.EndDate,
+ Schedule = c.Schedule
+ });
+
+ _mockUnitOfWork.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
+
+ // Act
+ var result = await _courseService.CreateCourseAsync(createCourseDto);
+
+ // Assert
+ result.Should().NotBeNull();
+ result.CourseId.Should().NotBe(Guid.Empty);
+ capturedCourse.Should().NotBeNull();
+ capturedCourse!.CourseId.Should().NotBe(Guid.Empty);
+ }
+}
diff --git a/api/CourseRegistration.Application.Tests/Validators/CreateCourseDtoValidatorTests.cs b/api/CourseRegistration.Application.Tests/Validators/CreateCourseDtoValidatorTests.cs
new file mode 100644
index 0000000..0c0f7c1
--- /dev/null
+++ b/api/CourseRegistration.Application.Tests/Validators/CreateCourseDtoValidatorTests.cs
@@ -0,0 +1,129 @@
+using CourseRegistration.Application.DTOs;
+using CourseRegistration.Application.Validators;
+using FluentAssertions;
+using Xunit;
+
+namespace CourseRegistration.Application.Tests.Validators;
+
+///
+/// Unit tests for CreateCourseDtoValidator
+///
+public class CreateCourseDtoValidatorTests
+{
+ private readonly CreateCourseDtoValidator _validator;
+
+ public CreateCourseDtoValidatorTests()
+ {
+ _validator = new CreateCourseDtoValidator();
+ }
+
+ [Fact]
+ public void Validate_WithValidDto_ShouldPass()
+ {
+ // Arrange
+ var dto = new CreateCourseDto
+ {
+ CourseName = "Introduction to C#",
+ Description = "Learn the fundamentals of C# programming",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(10),
+ EndDate = DateTime.UtcNow.AddDays(40),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var result = _validator.Validate(dto);
+
+ // Assert
+ result.IsValid.Should().BeTrue();
+ result.Errors.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void Validate_WithEmptyCourseName_ShouldFail()
+ {
+ // Arrange
+ var dto = new CreateCourseDto
+ {
+ CourseName = "",
+ Description = "Description",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(10),
+ EndDate = DateTime.UtcNow.AddDays(40),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var result = _validator.Validate(dto);
+
+ // Assert
+ result.IsValid.Should().BeFalse();
+ result.Errors.Should().Contain(e => e.PropertyName == "CourseName" && e.ErrorMessage.Contains("required"));
+ }
+
+ [Fact]
+ public void Validate_WithTooLongCourseName_ShouldFail()
+ {
+ // Arrange
+ var dto = new CreateCourseDto
+ {
+ CourseName = new string('A', 101),
+ Description = "Description",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(10),
+ EndDate = DateTime.UtcNow.AddDays(40),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var result = _validator.Validate(dto);
+
+ // Assert
+ result.IsValid.Should().BeFalse();
+ result.Errors.Should().Contain(e => e.PropertyName == "CourseName" && e.ErrorMessage.Contains("100 characters"));
+ }
+
+ [Fact]
+ public void Validate_WithStartDateInPast_ShouldFail()
+ {
+ // Arrange
+ var dto = new CreateCourseDto
+ {
+ CourseName = "Valid Course",
+ Description = "Description",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(-5),
+ EndDate = DateTime.UtcNow.AddDays(40),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var result = _validator.Validate(dto);
+
+ // Assert
+ result.IsValid.Should().BeFalse();
+ result.Errors.Should().Contain(e => e.PropertyName == "StartDate" && e.ErrorMessage.Contains("future"));
+ }
+
+ [Fact]
+ public void Validate_WithEndDateBeforeStartDate_ShouldFail()
+ {
+ // Arrange
+ var dto = new CreateCourseDto
+ {
+ CourseName = "Valid Course",
+ Description = "Description",
+ InstructorName = "John Doe",
+ StartDate = DateTime.UtcNow.AddDays(40),
+ EndDate = DateTime.UtcNow.AddDays(10),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var result = _validator.Validate(dto);
+
+ // Assert
+ result.IsValid.Should().BeFalse();
+ result.Errors.Should().Contain(e => e.PropertyName == "EndDate" && e.ErrorMessage.Contains("after start date"));
+ }
+}
diff --git a/api/CourseRegistration.sln b/api/CourseRegistration.sln
index 4bbe167..a527c94 100644
--- a/api/CourseRegistration.sln
+++ b/api/CourseRegistration.sln
@@ -11,6 +11,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseRegistration.Applicat
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseRegistration.Infrastructure", "CourseRegistration.Infrastructure\CourseRegistration.Infrastructure.csproj", "{234AB462-1115-42BF-ACC1-ED68930DD043}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseRegistration.Application.Tests", "CourseRegistration.Application.Tests\CourseRegistration.Application.Tests.csproj", "{BA79F6B1-5890-417E-9D48-C18AC5FAE920}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CourseRegistration.API.Tests", "CourseRegistration.API.Tests\CourseRegistration.API.Tests.csproj", "{CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -69,6 +73,30 @@ Global
{234AB462-1115-42BF-ACC1-ED68930DD043}.Release|x64.Build.0 = Release|Any CPU
{234AB462-1115-42BF-ACC1-ED68930DD043}.Release|x86.ActiveCfg = Release|Any CPU
{234AB462-1115-42BF-ACC1-ED68930DD043}.Release|x86.Build.0 = Release|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Debug|x64.Build.0 = Debug|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Debug|x86.Build.0 = Debug|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Release|x64.ActiveCfg = Release|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Release|x64.Build.0 = Release|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Release|x86.ActiveCfg = Release|Any CPU
+ {BA79F6B1-5890-417E-9D48-C18AC5FAE920}.Release|x86.Build.0 = Release|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Debug|x64.Build.0 = Debug|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Debug|x86.Build.0 = Debug|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Release|x64.ActiveCfg = Release|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Release|x64.Build.0 = Release|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Release|x86.ActiveCfg = Release|Any CPU
+ {CC45C3AB-4516-461C-A294-7A1EB7C8FDE9}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
From db9219e0ca9c20d8d4c405f686aed62c254fbfc3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 13:42:57 +0000
Subject: [PATCH 3/3] Add integration tests for add course API endpoint
Co-authored-by: Hemavathi15sg <224925058+Hemavathi15sg@users.noreply.github.com>
---
.../CoursesControllerIntegrationTests.cs | 117 ++++++++++++++++++
api/CourseRegistration.API.Tests/UnitTest1.cs | 10 --
api/CourseRegistration.API/Program.cs | 3 +
3 files changed, 120 insertions(+), 10 deletions(-)
create mode 100644 api/CourseRegistration.API.Tests/Controllers/CoursesControllerIntegrationTests.cs
delete mode 100644 api/CourseRegistration.API.Tests/UnitTest1.cs
diff --git a/api/CourseRegistration.API.Tests/Controllers/CoursesControllerIntegrationTests.cs b/api/CourseRegistration.API.Tests/Controllers/CoursesControllerIntegrationTests.cs
new file mode 100644
index 0000000..b343a82
--- /dev/null
+++ b/api/CourseRegistration.API.Tests/Controllers/CoursesControllerIntegrationTests.cs
@@ -0,0 +1,117 @@
+using System.Net;
+using System.Net.Http.Json;
+using System.Text.Json;
+using CourseRegistration.Application.DTOs;
+using FluentAssertions;
+using Microsoft.AspNetCore.Mvc.Testing;
+using Xunit;
+
+namespace CourseRegistration.API.Tests.Controllers;
+
+///
+/// Integration tests for CoursesController focusing on CreateCourse endpoint
+///
+public class CoursesControllerIntegrationTests : IClassFixture>
+{
+ private readonly WebApplicationFactory _factory;
+ private readonly HttpClient _client;
+
+ public CoursesControllerIntegrationTests(WebApplicationFactory factory)
+ {
+ _factory = factory;
+ _client = factory.CreateClient();
+ }
+
+ [Fact]
+ public async Task CreateCourse_WithValidData_ShouldReturn201Created()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Integration Test Course",
+ Description = "This is a test course created during integration testing",
+ InstructorName = "Dr. Test",
+ StartDate = DateTime.UtcNow.AddDays(30),
+ EndDate = DateTime.UtcNow.AddDays(60),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.Created);
+
+ var content = await response.Content.ReadAsStringAsync();
+ content.Should().NotBeNullOrEmpty();
+
+ var apiResponse = JsonSerializer.Deserialize(content);
+ apiResponse.GetProperty("success").GetBoolean().Should().BeTrue();
+ apiResponse.GetProperty("data").GetProperty("courseName").GetString().Should().Be(createCourseDto.CourseName);
+ }
+
+ [Fact]
+ public async Task CreateCourse_WithStartDateInPast_ShouldReturn400BadRequest()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Invalid Course",
+ Description = "Course with past start date",
+ InstructorName = "Dr. Test",
+ StartDate = DateTime.UtcNow.AddDays(-5),
+ EndDate = DateTime.UtcNow.AddDays(30),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
+ }
+
+ [Fact]
+ public async Task CreateCourse_WithEndDateBeforeStartDate_ShouldReturn400BadRequest()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Invalid Course",
+ Description = "Course with end date before start date",
+ InstructorName = "Dr. Test",
+ StartDate = DateTime.UtcNow.AddDays(60),
+ EndDate = DateTime.UtcNow.AddDays(30),
+ Schedule = "MWF 10:00-11:30"
+ };
+
+ // Act
+ var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
+ }
+
+ [Fact]
+ public async Task CreateCourse_ShouldReturnLocationHeader()
+ {
+ // Arrange
+ var createCourseDto = new CreateCourseDto
+ {
+ CourseName = "Location Header Test Course",
+ Description = "Testing location header",
+ InstructorName = "Dr. Location",
+ StartDate = DateTime.UtcNow.AddDays(30),
+ EndDate = DateTime.UtcNow.AddDays(60),
+ Schedule = "MWF 09:00-10:30"
+ };
+
+ // Act
+ var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);
+
+ // Assert
+ response.StatusCode.Should().Be(HttpStatusCode.Created);
+ response.Headers.Location.Should().NotBeNull();
+ response.Headers.Location!.ToString().Should().Contain("/api/Courses/");
+ }
+}
diff --git a/api/CourseRegistration.API.Tests/UnitTest1.cs b/api/CourseRegistration.API.Tests/UnitTest1.cs
deleted file mode 100644
index 0d806f1..0000000
--- a/api/CourseRegistration.API.Tests/UnitTest1.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace CourseRegistration.API.Tests;
-
-public class UnitTest1
-{
- [Fact]
- public void Test1()
- {
-
- }
-}
diff --git a/api/CourseRegistration.API/Program.cs b/api/CourseRegistration.API/Program.cs
index 2c174da..377e494 100644
--- a/api/CourseRegistration.API/Program.cs
+++ b/api/CourseRegistration.API/Program.cs
@@ -299,3 +299,6 @@ static async Task SeedDatabase(CourseRegistrationDbContext context)
Log.Information("Database seeded successfully with {StudentCount} students, {CourseCount} courses, and {RegistrationCount} registrations.",
students.Length, courses.Length, registrations.Length);
}
+
+// Make Program accessible for integration tests
+public partial class Program { }