diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
index c93b734..4fbabed 100644
--- a/.github/workflows/ci-cd.yml
+++ b/.github/workflows/ci-cd.yml
@@ -1,25 +1,31 @@
name: ASP.NET Core 8 API CI/CD
+
on:
push:
branches: [main]
pull_request:
- branches: [main]
+ branches: [main]
jobs:
- build: # Fisrt we we will setup only build job
- runs-on: ubuntu-latest # <-- OS to run the job
- env: # Environment variables
- SOLUTION_PATH: SimpleAPI/SimpleAPI.sln #// Path to the solution file
+ build:
+ runs-on: ubuntu-latest
+ env:
+ SOLUTION_PATH: SimpleAPI/SimpleAPI.sln
+ TEST_PROJECT_PATH: SimpleAPI.Test/SimpleAPI.Test.csproj
steps:
- - name: Checkout-code # Step 1: Checkout the code from repository
- uses: actions/checkout@v3 # This is a predefined action in GutHib to checkout code
-
- - name: Setup .NET 8 SDK # Step 2: we will setup .net 8 sdk for build
- uses: actions/setup-dotnet@v3 # Predefined action to setup dotnet
- with: #<-- provide parameters to the action
- dotnet-version: '8.0.x' # Specify the .NET version to install
- - name: Cache NuGet Packages # Step 2.1: Cache NuGet packages to speed up builds
+ # Step 1: Checkout the code from repository
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ # Step 2: Setup .NET 8 SDK
+ - name: Setup .NET 8 SDK
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: '8.0.x'
+
+ # Step 2.1: Cache NuGet packages
+ - name: Cache NuGet Packages
uses: actions/cache@v3
with:
path: ~/.nuget/packages
@@ -27,10 +33,14 @@ jobs:
restore-keys: |
${{ runner.os }}-nuget-
- - name: Restore dependencies # Step 3: Restore the dependencies
- run: dotnet restore $SOLUTION_PATH
-
- - name: Build solution # Step 4: Build the solution
- run: dotnet build $SOLUTION_PATH --no-restore --configuration Release
+ # Step 3: Restore dependencies
+ - name: Restore dependencies
+ run: dotnet restore $SOLUTION_PATH
+ # Step 4: Build the solution
+ - name: Build solution
+ run: dotnet build $SOLUTION_PATH --no-restore --configuration Release
+ # Step 5: Run Unit Tests (xUnit)
+ - name: Run unit tests
+ run: dotnet test $TEST_PROJECT_PATH --no-build --configuration Release --verbosity normal
\ No newline at end of file
diff --git a/SimpleAPI.Test/SimpleAPI.Test.csproj b/SimpleAPI.Test/SimpleAPI.Test.csproj
new file mode 100644
index 0000000..05b98b9
--- /dev/null
+++ b/SimpleAPI.Test/SimpleAPI.Test.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SimpleAPI.Test/UsersControllerTests.cs b/SimpleAPI.Test/UsersControllerTests.cs
new file mode 100644
index 0000000..deffd3d
--- /dev/null
+++ b/SimpleAPI.Test/UsersControllerTests.cs
@@ -0,0 +1,47 @@
+using Microsoft.AspNetCore.Mvc.Testing;
+using Microsoft.VisualStudio.TestPlatform.TestHost;
+using System.Net.Http.Json;
+using Xunit;
+
+namespace SimpleAPI.Test
+{
+ public class UsersControllerTests:IClassFixture>
+ {
+ private readonly HttpClient _httpClient;
+
+ public UsersControllerTests(WebApplicationFactory factory)
+ {
+ _httpClient = factory.CreateClient();// ← this talks to your in-memory API
+ }
+ [Fact]
+ public async Task GetAllUsers_ReturnsList()
+ {
+ var response = await _httpClient.GetAsync("/api/users");
+ response.EnsureSuccessStatusCode();
+ var json = await response.Content.ReadAsStringAsync();
+ Assert.Contains("Ravinder", json);
+ }
+ [Theory]
+ [InlineData(1)]
+ [InlineData(2)]
+ public async Task GetUser_ById_ReturnsCorrectUser(int id)
+ {
+ // Act
+ var response = await _httpClient.GetAsync($"/api/users/{id}");
+ response.EnsureSuccessStatusCode();
+
+ // Deserialize JSON to a C# object
+ var user = await response.Content.ReadFromJsonAsync();
+
+ // Assert
+ Assert.NotNull(user);
+ Assert.Equal(id, user!.Id);
+ Assert.Equal($"User {id}", user.Name);
+ }
+ }
+ public class UserDto
+ {
+ public int Id { get; set; }
+ public string? Name { get; set; }
+ }
+}
diff --git a/SimpleAPI/Controllers/UsersController.cs b/SimpleAPI/Controllers/UsersController.cs
new file mode 100644
index 0000000..5b1eb8d
--- /dev/null
+++ b/SimpleAPI/Controllers/UsersController.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Mvc;
+
+namespace SimpleAPI.Controllers
+{
+ [Route("api/[controller]")]
+ [ApiController]
+ public class UsersController : ControllerBase
+ {
+ [HttpGet]
+ public IActionResult GetAllUsers()
+ {
+ var users = new[]
+ {
+ new { Id = 1, Name = "Ravinder" },
+ new { Id = 2, Name = "John" }
+ };
+ return Ok(users);
+ }
+
+ [HttpGet("{id}")]
+ public IActionResult GetUser(int id)
+ {
+ return Ok(new { Id = id, Name = $"User {id}" });
+ }
+ }
+}
diff --git a/SimpleAPI/Program.cs b/SimpleAPI/Program.cs
index a80486a..c4e133a 100644
--- a/SimpleAPI/Program.cs
+++ b/SimpleAPI/Program.cs
@@ -1,7 +1,8 @@
-var builder = WebApplication.CreateBuilder(args);
+var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddControllers(); // ✅ Add this line
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
@@ -15,7 +16,10 @@
}
//app.UseHttpsRedirection();
-
+// ✅ Add this before MapControllers()
+app.UseRouting();
+// Map your controllers 👇
+app.MapControllers();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
@@ -42,3 +46,5 @@ record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
+// ✅ Add this at the end
+public partial class Program { }
diff --git a/SimpleAPI/SimpleAPI.csproj b/SimpleAPI/SimpleAPI.csproj
index 8b2086b..1ae9e45 100644
--- a/SimpleAPI/SimpleAPI.csproj
+++ b/SimpleAPI/SimpleAPI.csproj
@@ -4,6 +4,7 @@
net8.0
enable
enable
+ true
diff --git a/SimpleAPI/SimpleAPI.sln b/SimpleAPI/SimpleAPI.sln
index a62a6e5..430bb88 100644
--- a/SimpleAPI/SimpleAPI.sln
+++ b/SimpleAPI/SimpleAPI.sln
@@ -4,6 +4,8 @@ VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleAPI", "SimpleAPI.csproj", "{6299BDDD-37C4-D32F-2AC5-6E9916FA39B9}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleAPI.Test", "..\SimpleAPI.Test\SimpleAPI.Test.csproj", "{0BDD7F6D-4893-49BB-B452-9118D720E629}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -14,6 +16,10 @@ Global
{6299BDDD-37C4-D32F-2AC5-6E9916FA39B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6299BDDD-37C4-D32F-2AC5-6E9916FA39B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6299BDDD-37C4-D32F-2AC5-6E9916FA39B9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0BDD7F6D-4893-49BB-B452-9118D720E629}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0BDD7F6D-4893-49BB-B452-9118D720E629}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0BDD7F6D-4893-49BB-B452-9118D720E629}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0BDD7F6D-4893-49BB-B452-9118D720E629}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE