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