Featured resource
2026 Tech Forecast
2026 Tech Forecast

1,500+ tech insiders, business leaders, and Pluralsight Authors share their predictions on what’s shifting fastest and how to stay ahead.

Download the forecast
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • Core Tech
Labs

Guided: Testing ASP.NET Core 10 Web APIs

In this lab, you will write and run automated tests for an existing ASP.NET Core 10 Web API to validate routing, validation, authentication, and error-handling behavior without relying on fragile mocks. You will use in-memory hosting and realistic HTTP pipelines to ensure that the API behaves correctly under real-world conditions.

Lab platform
Lab Info
Level
Intermediate
Last updated
Apr 02, 2026
Duration
35m

Contact sales

By clicking submit, you agree to our Privacy Policy and Terms of Use, and consent to receive marketing emails from Pluralsight.
Table of Contents
  1. Challenge

    Introduction

    In this lab, you will learn how to test an ASP.NET Core Web API using both unit tests and integration tests. Automated testing helps ensure that your API behaves correctly as the application evolves and new features are added.

    You will go through the below points in this lab:

    • Analyze the risks of relying only on manual API testing
    • Write unit tests to validate controller decision logic
    • Implement integration tests using in-memory hosting
    • Verify routing, validation, and HTTP responses
    • Test authentication and authorization behavior
    • Evaluate how to balance isolated tests with realistic API testing

    Use Case

    You are working as a developer on a Product Management Web API used by internal business applications.

    The API provides endpoints to:

    • Retrieve products
    • Create products
    • Update product information
    • Delete products

    The application currently works correctly when tested manually using Swagger or Postman. However, the project does not include any automated unit or integration tests for the API.

    Without these automated tests, several issues may go unnoticed when the system changes, such as:

    • Routing misconfigurations
    • Validation rules not being enforced
    • Middleware or authentication changes affecting access
    • Incorrect HTTP responses being returned

    Automated testing ensures that these behaviors are verified every time the code changes.


    What You Will Build

    In this lab, you will progressively introduce a testing strategy for the API. You will start by writing unit tests that validate controller logic in isolation. Then, you will introduce integration tests that execute the full HTTP request pipeline to verify routing, validation, and authentication behavior.

    By the end of the lab, your API will be supported by a structured test suite that verifies both application logic and framework-integrated behavior.

    Note: Each step contains tasks clearly marked with comments like // Task 3.1

    info> If you get stuck on a task, you can view the solution in the solution folder in your Filetree, or click the Task Solution link at the bottom of each task after you've attempted it.

  2. Challenge

    Understanding the API Testing Strategy

    In this step, you will review the existing ASP.NET Core application and understand how it will be tested throughout this lab.

    The application is available in the /ProductApi/Api project and exposes endpoints to manage products.

    You will work with the /ProductApi/Tests project, which contains automated tests that validate the behavior of the API.


    Overview of the API

    The /ProductApi/Api folder contains a controller named ProductsController that provides the following endpoints:

    • GET /products → Retrieve all products
    • POST /products → Create a new product
    • DELETE /products/{id} → Delete a product

    These endpoints will be tested in the upcoming steps.


    Controller and Dependency Setup

    The controller depends on a repository:

    IProductRepository
    

    This repository is responsible for:

    • Storing product data
    • Retrieving products
    • Deleting products

    It is injected using ASP.NET Core’s dependency injection system.


    Validation Behavior

    The POST /products endpoint includes validation logic.

    If invalid input is provided, the API returns:

    400 BadRequest
    

    You will write tests to verify this behavior.


    Authentication Behavior

    Some endpoints require authentication.

    • If a request is sent without authentication:

      401 Unauthorized
      
    • If the request is authenticated:

      200 OK
      

    In later steps, you will simulate authentication using a test-specific handler.


    Understanding the API Testing Strategy

    In this step, you will also understand how automated API testing is structured and why different types of tests are needed.


    Why Automated API Testing Matters

    When an API grows and multiple developers contribute to it, several types of changes can affect behavior:

    • A developer modifies routing attributes
    • Validation attributes are added or removed
    • Middleware configuration changes
    • Authorization policies are updated
    • Response structures change

    Even though the application still compiles and starts successfully, the API behavior might have changed.

    Without automated tests, these changes may only be discovered later by users or systems that depend on the API.

    Automated tests provide a reliable way to verify that the API continues to behave as expected.


    Two Common Types of API Tests

    When testing ASP.NET Core Web APIs, two types of automated tests are commonly used:


    Unit Tests

    Unit tests validate small pieces of application logic in isolation.

    For a Web API, unit tests typically verify:

    • Controller decision logic
    • Business rule branching
    • Returned result types

    For example, a controller might return:

    • NotFound() if an item does not exist
    • Ok() if the item is successfully retrieved

    Unit tests are fast and focused but do not verify the full HTTP request pipeline.


    Integration Tests

    Integration tests validate how the API behaves when a real HTTP request is executed.

    These tests run the full ASP.NET Core request pipeline and verify:

    • Routing behavior
    • HTTP status codes
    • Model binding and validation
    • Middleware execution
    • Authentication and authorization rules

    Integration tests simulate real client requests and ensure the API behaves correctly end-to-end.


    Combining Both Testing Approaches

    A well-designed API test suite typically includes both types of tests:

    | Test Type | Purpose | | ----------------- | ------------------------------------------------ | | Unit Tests | Validate controller logic and decision branches | | Integration Tests | Validate real HTTP behavior and request pipeline |

    Using both approaches provides better coverage while keeping tests fast and maintainable.


    What You Will Be Testing

    Based on this setup, you will validate:

    • Correct API responses for valid requests
    • Validation failures for invalid input
    • Authorization behavior for protected endpoints
    • API responses and status codes for valid requests
    • Validation behavior for invalid input
    • Authorization behavior for protected endpoints

    In the next step, you will begin implementing your first unit tests to validate the decision logic inside the ProductsController.

  3. Challenge

    Writing Unit Tests for Controller Logic

    In this step, you will create your first unit tests to verify the decision logic inside the ProductsController. ### Understanding Controller Decision Logic

    File: /ProductApi/Api/ProductController.cs

    Consider the following controller method used to retrieve a product by its ID.

    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        var product = _repository.Get(id);
    
    		if (product == null)
    		{
    				return NotFound();
    		}
    
        return Ok(product);
    }
    

    This method produces two outcomes:

    • If the repository returns null, the controller returns NotFound() (HTTP 404)
    • If a product is found, the controller returns Ok(product) (HTTP 200)

    To isolate the controller logic, you will mock the repository dependency so that the controller receives predictable input. Now that you have configured the mock repository to simulate a missing product, the controller will receive null when it attempts to retrieve the product.

    Next, you will verify how the controller responds to this scenario by asserting the returned result. Review the test method GetById_ReturnsOk_WhenProductExists in ProductsControllerTests, which covers the scenario where the product exists.


    In this step, you implemented ProductsControllerTests class.

    These tests are designed to verify that:

    • The controller returns 404 Not Found when a product does not exist.
    • The controller returns 200 OK when a product is found.

    These unit tests validate the controller’s decision logic in isolation. However, they do not verify how the API behaves when accessed through HTTP requests.

    In the next step, you will introduce integration tests to validate routing and the full ASP.NET Core request pipeline.

  4. Challenge

    Testing the API with Integration Tests

    In this step, you will write an integration test that sends an actual HTTP request to the API and verifies the response.


    Understanding Integration Testing in ASP.NET Core

    Open Tests/CustomWebApplicationFactory.cs.

    This class uses WebApplicationFactory to start the ASP.NET Core application during test execution.

    Using this:

    • The API runs without starting a real web server
    • The full request pipeline is executed
    • Tests can interact with the API using HTTP

    In this setup:

    • CustomWebApplicationFactory starts the API during the test run
    • CreateClient() creates an HttpClient connected to the test server
    • The test uses _client to send HTTP requests to the API endpoints
      With this change, the integration test now sends an HTTP request to the /products endpoint and verifies that the API returns a successful response. This helps confirm that the endpoint is reachable and that the API can process the request correctly through the configured request pipeline.

    In the next step, you will test how the API handles invalid input and verify that it returns the expected validation response.

  5. Challenge

    Validation and Error Testing

    APIs must also handle invalid input correctly. When a request does not contain the required data, the API should reject it and return the appropriate HTTP response.

    In this step, you will complete a validation test that sends invalid input to the API and verifies that the API returns a 400 Bad Request response. With this change, the validation test now verifies that the API rejects invalid input and returns a 400 Bad Request response. This helps confirm that the API handles invalid requests correctly during test execution.

    In the next step, you will test how the API handles unauthorized access and verify that protected endpoints return the expected response.

  6. Challenge

    Authentication and Authorization Tests

    APIs may also protect certain endpoints so that only authenticated users can access them. When a request is sent without the required credentials, the API should reject it and return the appropriate HTTP response.

    In this lab, authentication is simplified using a custom handler implemented in TestAuthHandler.cs. This handler extends the ASP.NET Core authentication pipeline and overrides the default behavior to simulate authentication during tests. Instead of validating real tokens, it inspects incoming requests for a predefined test header.

    • If the expected header is present, the handler creates a valid ClaimsPrincipal and marks the request as authenticated.
    • If the header is missing, the handler does not authenticate the request, and the API responds with 401 Unauthorized.

    This approach allows you to control authentication behavior directly within your tests, without depending on external systems like identity providers or token services.

    In this step, you will complete a security test that sends a request to a protected endpoint without authentication and verifies that the API correctly rejects it by returning a 401 Unauthorized response. With this change, the security test now verifies that the protected endpoint rejects unauthenticated requests and returns the expected HTTP response.

    With these changes, the security tests now verify both authorization outcomes:

    • unauthenticated requests are rejected
    • authenticated requests are allowed

    This helps confirm that the API enforces access rules correctly during test execution.


    Moment of truth! Now run all the tests using the dotnet test Tests command. Once all tests pass successfully, it confirms that the API logic, validation, and authentication behavior are working correctly.

    In the next step, you will review the completed test suite and evaluate how unit tests and integration tests work together to provide reliable API coverage.

  7. Challenge

    Evaluating Test Design

    At this point, your tests cover controller logic, endpoint behavior, validation, and authorization. You can now review how these tests work together and evaluate whether the overall testing approach has the right balance between isolation, realism, and performance.

    In this step, you will review the completed tests, compare the role of unit tests and integration tests, and identify practical guidelines for building a maintainable API testing strategy.


    Reviewing the Completed Tests

    Open the test project and review the following files:

    • ProductsControllerTests.cs
    • ProductsIntegrationTests.cs
    • ProductValidationTests.cs
    • ProductAuthTests.cs

    Each file focuses on a different aspect of API behavior.


    What Each Test Type Validates

    The completed tests include both unit tests and integration tests.

    | Test File | Test Type | What It Validates | |---|---|---| | ProductsControllerTests.cs | Unit Test | Controller decision logic | | ProductsIntegrationTests.cs | Integration Test | Endpoint accessibility and successful HTTP responses | | ProductValidationTests.cs | Integration Test | Validation behavior for invalid input | | ProductAuthTests.cs | Integration Test | Authorization behavior for protected endpoints |

    This separation ensures that each part of the API is tested at the appropriate level.


    Comparing Unit Tests and Integration Tests

    • Unit tests verify controller logic in isolation and are typically faster to run.
    • Integration tests verify routing, validation, authorization, and real HTTP behavior, but they usually take longer because they execute more of the application.

    A balanced testing strategy uses unit tests for isolated decision logic and integration tests for behavior that must be validated through the full request pipeline.


    Guidelines for Sustainable API Testing

    To keep API tests maintainable over time, follow these guidelines:

    • Use unit tests for controller logic and decision branches
    • Use integration tests for routing, validation, and authorization behavior
    • Test observable behavior instead of internal implementation details
    • Avoid tightly coupling tests to framework internals
    • Keep each test focused on one clear outcome

    These guidelines help ensure that tests remain reliable, readable, and useful as the API evolves.


    In the next step, you will review what you completed and identify practical next steps for expanding your API testing strategy.

  8. Challenge

    Conclusion and next steps

    You have now completed the lab and built a practical testing foundation for an ASP.NET Core Web API.


    Lab Summary

    In this lab, you learned how to:

    • Write unit tests for ASP.NET Core Web API controller logic
    • Run integration tests using WebApplicationFactory and HttpClient
    • Verify validation and authorization behavior through automated tests
    • Evaluate the balance between isolation, realism, and maintainability in a test suite

    You now have a practical approach for testing ASP.NET Core Web APIs using a combination of focused unit tests and realistic integration tests.


    Next Steps

    You can continue improving this testing strategy by exploring the following areas:

    • Add tests for update and delete scenarios with different outcomes
    • Verify response payloads, not only status codes
    • Test custom error responses and problem details payloads
    • Add more authorization scenarios for different roles or policies
    • Integrate the test suite into a CI pipeline so tests run automatically on every change

    These next steps will help you build a stronger and more maintainable API testing practice.

About the author

Amar Sonwani is a software architect with more than twelve years of experience. He has worked extensively in the financial industry and has expertise in building scalable applications.

Real skill practice before real-world application

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight