A .NET 9 API project for managing user information with EF Core and SQLite integration.
- User management with CRUD operations
- Repository pattern implementation
- Entity Framework Core with SQLite
- TDD approach with NUnit, Shouldly, and Moq
This project follows TDD (Test-Driven Development) practices and uses:
- NUnit for unit and integration tests
- Shouldly for fluent assertions
- Moq for mocking dependencies
- Entity Framework Core for data access
This project includes code coverage analysis using Coverlet and ReportGenerator.
To generate a code coverage report:
- Run the
code-coverage.shscript:./code-coverage.sh - View the HTML report at
coverage-report/index.html
The script will:
- Execute all tests with coverage collection
- Generate an HTML report with detailed metrics
- Display coverage results by class and method
The project includes a comprehensive HTTP request file (Users.Api.http) that demonstrates all API endpoints and validation scenarios. This file can be used with REST Client extensions in VS Code, JetBrains Rider, or other HTTP client tools.
The API implements JWT-based authentication. To access protected endpoints, you need to:
-
Register a new user:
- Use the
/api/auth/registerendpoint - Provide email, password, and user details
- Use the
-
Login to get a token:
- Use the
/api/auth/loginendpoint with email and password - The response includes a JWT token
- Use the
-
Use the token for authenticated requests:
- Add an
Authorization: Bearer {token}header to requests - Replace
{token}with the actual JWT token
- Add an
The Users.Api.http file includes a variable @token that can be set with your JWT token to test authenticated endpoints.
-
Public endpoints (no authentication required):
GET /api/users- Get all usersPOST /api/auth/register- Register a new userPOST /api/auth/login- Login and get a token
-
Protected endpoints (require authentication):
GET /api/users/{id}- Get a specific userPOST /api/users- Create a userPUT /api/users/{id}- Update a userDELETE /api/users/{id}- Delete a userGET /api/auth/validate- Validate a token
-
Authentication Flow:
- Register a new user
- Login to obtain a JWT token
- Validate token
-
User Management:
- GET All Users: Public endpoint to list all users
- GET User by ID: Retrieve user details by ID (authenticated)
- POST - Create a new user: Create a user with address and employment information
- POST - Create a user (duplicate email validation): Test email uniqueness validation
- POST - Create a user (employment date validation): Test validation of employment dates
- PUT - Update user (valid data): Update all user information including address and employment
- PUT - Update user (address changes only): Test partial updates with address changes
- PUT - Update user (employment changes only): Test partial updates with employment changes
- PUT - Update user (invalid employment dates): Test validation of employment dates during update
- PUT - Update user (duplicate email): Test email uniqueness validation during update
- DELETE - Delete a user: Remove a user from the system
- Make sure your API is running at the URL specified in the
.httpfile (default:https://localhost:3000) - Open
Users.Api.httpin an editor with REST Client support - Run the authentication requests first to get a valid token
- Update the
@tokenvariable with your JWT token if needed - Run the desired API requests with authentication
- Review the responses to verify correct behavior
These sample requests help verify that the API correctly implements all validation rules:
- Email uniqueness across all users
- Employment end date must be after start date
- Required fields validation
The API includes Swagger/OpenAPI documentation, providing interactive exploration of all endpoints, request/response models, and validation requirements.
- Development Environment: Available at
/swaggerwhen running locally - Production Environment: Available at
/api-docson the deployed application
- Interactive Documentation: Test API endpoints directly from the browser
- Request Validation: Shows required fields and data formats
- Response Schemas: Displays the structure of all response objects
- Model Documentation: Describes all entities with their properties and validation rules
The API implements JWT authentication which is fully integrated with Swagger UI:
- Use the
/api/auth/registerendpoint to create a new account - Use the
/api/auth/loginendpoint to get a JWT token - Click the "Authorize" button (lock icon) at the top of the Swagger UI
- Enter your token in the format:
Bearer {your-token}(include the word "Bearer" followed by a space) - Click "Authorize" to apply the token to all subsequent API calls
- You can now test protected endpoints directly from Swagger UI
Protected endpoints are marked with a lock icon in the Swagger UI. Public endpoints can be accessed without authentication.
The API is deployed on Render.com and is accessible at https://users-api-jhnp.onrender.com/.
To deploy this application on Render:
-
Prepare your repository:
- Ensure your repository has a
Dockerfile(included in this repo) - Push changes to GitHub
- Ensure your repository has a
-
Create a Web Service on Render:
- Sign up/Sign in to Render.com
- Create a "New Web Service"
- Connect your GitHub repository
- Choose "Docker" as the environment
- Configure the service:
- Set a name for your service
- Select the appropriate region
- Choose the branch to deploy
- Set the Docker port to
10000(matches the Dockerfile)
-
Configure Environment Variables:
- Add the following environment variables:
ConnectionStrings__DefaultConnection: For the database connectionASPNETCORE_ENVIRONMENT: Set toProductionJWT_SECRET_KEY: A secure random string for JWT token signing (min 32 characters)- Any other application-specific variables
- Add the following environment variables:
-
Deploy:
- Click "Create Web Service"
- Wait for the build and deployment to complete
-
Accessing the API:
- Once deployed, your API will be available at
https://[service-name].onrender.com/ - Use the provided HTTP request file to test the endpoints against the deployed API
- Once deployed, your API will be available at
In Render.com, use double underscores (__) for nested configuration values from appsettings.json. For example:
ConnectionStrings__DefaultConnection=Data Source=users.db
Logging__LogLevel__Default=Information
The project includes GitHub Actions workflows for:
- Continuous Integration (build and test)
- Code Quality Analysis
To enforce quality standards and prevent merging PRs when builds or tests fail:
- Go to repository Settings > Branches > Branch protection rules > Add rule
- Under "Branch name pattern" enter
main - Enable the following options:
- ✅ Require a pull request before merging
- ✅ Require status checks to pass before merging
- ✅ Require branches to be up to date before merging
- Under "Status checks that are required":
- Search for and select
build-and-test(from the .NET CI workflow)
- Search for and select
- Optionally, enable these additional protections:
- ✅ Require conversation resolution before merging
- ✅ Require linear history
- ✅ Do not allow bypassing the above settings
With these settings, GitHub will prevent merging pull requests to the main branch until all the required status checks (including build and tests) pass successfully.
- Clone the repository
- Restore dependencies:
dotnet restore - Run the tests:
dotnet test - Run the API:
dotnet run --project Users.Api