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 an ASP.NET Core 10 Application

Learn how to write and execute automated tests for a real ASP.NET Core 10 Web API application. In this guided lab, you'll set up a testing environment using xUnit and Moq, write unit tests to verify service-layer logic in isolation, and implement integration tests that validate API endpoints end-to-end. By the end, you'll run the full test suite and interpret results to confirm correct application behavior.

Lab platform
Lab Info
Level
Advanced
Last updated
Jun 24, 2026
Duration
45m

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

    Set Up Your Testing Environment

    Set Up Your Testing Environment

    Welcome to the Book Management API testing lab!

    The Scenario

    You've just joined the team that maintains a Book Management API built with ASP.NET Core 10. The application works, but it has zero test coverage. Your first assignment: build an automated test suite so the team can ship with confidence.

    The Architecture

    The application follows a layered architecture:

    Controllers -> Services -> Repository -> Data Store
    
    • Models — Book entity with properties: Id, Title, Author, ISBN, PublishedYear
    • Data — IBookRepository interface and an in-memory BookRepository implementation
    • Services — IBookService interface and BookService with business logic (validation, null checks)
    • Controllers — BooksController exposing REST endpoints: GET all, GET by id, POST

    Your Goal

    You'll create a test project, write unit tests for the service layer, write integration tests for the API, run the full suite, and analyze the results.

    What You'll Learn

    • Unit testing — testing a single class in isolation using mock dependencies
    • Integration testing — testing the full HTTP pipeline from request to response
    • Test execution — running, filtering, and configuring test output
    • Result analysis — reading test output and identifying gaps in coverage

    Take a moment to read through BookService.cs and BooksController.cs — these are the classes you'll write tests against.

    info> If you get stuck, click the Task Solution link at the bottom of any task to view the solution code.

  2. Challenge

    Write Unit Tests for the Service Layer

    Now that the test project is set up, it's time to write your first tests.

    What Are Unit Tests?

    Unit tests verify the behavior of a single class or method in isolation. They test one "unit" of code at a time, without involving external dependencies like databases, file systems, or HTTP endpoints.

    Why Test the Service Layer?

    The BookService class contains business logic — validation rules, data transformations, error handling. This is exactly the kind of code that benefits from unit testing because:

    • It has clear inputs and outputs
    • It depends on abstractions (IBookRepository) that can be mocked
    • It contains business rules that should not break during refactoring

    The Arrange-Act-Assert Pattern

    Unit tests generally follow this structure:

    1. Arrange — Set up the test data and mock dependencies
    2. Act — Call the method under test
    3. Assert — Verify the expected outcome

    What You'll Test

    In this step, you'll write unit tests for three methods in BookService:

    • GetAllBooks() — returns all books from the repository
    • GetBookById(int id) — returns a single book or null
    • AddBook(Book book) — validates and adds a new book

    For each test, you'll mock IBookRepository using Moq to control what the repository returns and verify how the service interacts with it.

  3. Challenge

    Write Integration Tests for the API Endpoints

    Great work on the unit tests! Now let's move to integration testing.

    Unit Tests vs. Integration Tests

    Unit tests isolate a single class. Integration tests verify that multiple components work together correctly. For a web API, this means testing the full HTTP pipeline:

    HTTP Request -> Routing -> Controller -> Service -> Repository -> HTTP Response
    

    WebApplicationFactory

    ASP.NET Core provides WebApplicationFactory<TEntryPoint> which spins up an in-memory test server. This lets you send real HTTP requests and inspect real responses — no external dependencies needed.

    public class BooksControllerTests : IClassFixture<WebApplicationFactory<Program>>
    {
        private readonly HttpClient _client;
    
        public BooksControllerTests(WebApplicationFactory<Program> factory)
        {
            _client = factory.CreateClient();
        }
    }
    

    What You'll Test

    • GET /api/books — should return 200 OK with a JSON array
    • POST /api/books — should return 201 Created with the new book and a Location header
    • GET /api/books/{id} — should return 200 for valid IDs and 404 for non-existent ones

    Each test sends a real HTTP request and asserts on the response status code, headers, and body.

  4. Challenge

    Run and Configure the Full Test Suite

    You've written unit tests and integration tests. Now let's learn how to run, filter, and configure the test suite like a professional.

    Running the Full Suite

    So far you've been filtering tests to run specific subsets. To run everything:

    dotnet run --project BookApi.Tests/BookApi.Tests.csproj
    

    This runs all tests in the project. The xUnit v3 runner executes the test project as a console application.

    Filtering Tests

    xUnit v3 uses native filter flags passed after --:

    # Run only unit tests
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj -- -namespace "BookApi.Tests.UnitTests"
    
    # Run only integration tests
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj -- -namespace "BookApi.Tests.IntegrationTests"
    
    # Run a specific test method (wildcards supported)
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj -- -method "*AddBook*"
    

    Test Output Configuration

    Control the verbosity of test output with reporter options:

    # Default reporter (standard progress)
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj
    
    # Verbose output with detailed timing
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj -- -reporter verbose
    
    # Generate a TRX report for CI/CD systems
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj -- -trx "TestResults/results.trx"
    

    CI Configuration

    In continuous integration environments, you might want diagnostic tools:

    # Generate a hang dump if a test hangs (useful for debugging)
    dotnet run --project BookApi.Tests/BookApi.Tests.csproj -- -hangdump
    

    Understanding how to run and configure tests is essential for maintaining a healthy test suite in real projects.

  5. Challenge

    Analyze Test Results

    You've built a test suite and learned how to run it. Now comes the real skill: diagnosing a failure, fixing a defect, and verifying the fix.

    The Scenario

    A teammate mentioned that the GET /api/books/{id} endpoint might not handle missing books correctly. You notice the test suite has no test for a non-existent book ID — a gap in coverage.

    Diagnosing a Failure

    You'll start by writing the missing test, observing the failure, and tracing it to the root cause in the controller.

    Reading Test Output

    When the test fails, the output tells you:

    1. Which test failed — the fully qualified test name
    2. What assertion failed — the specific Assert call that was not satisfied
    3. What was expected vs. actual — for comparison assertions
    4. Stack trace — where in the test code the failure occurred

    Understanding Failures

    Rather than immediately fixing the code, take time to understand:

    • What the test expected and what it received
    • Which code path produced the incorrect result
    • Whether the bug is in the test or the production code

    Fix and Verify

    After identifying the defect, apply the fix and re-run the entire suite to confirm:

    • The failing test now passes
    • No other tests were broken by the change

    Identifying Coverage Gaps

    In BookService.AddBook(), we test null input and empty title. After Task 5.2, we also validate empty author. But what about:

    • Whitespace-only title (" ") — does IsNullOrWhiteSpace catch it?
    • A book with the minimum valid fields only?
    • A valid book with the longest possible title (200 characters)?

    These are edge cases that thorough testers should consider. For integration tests, consider gaps like POST with missing required fields (the controller returns 400 BadRequest for invalid models).

    Best Practices

    • Read test output carefully before assuming a failure is a bug in the code
    • Use verbose output to understand exactly which tests ran
    • Regularly review test coverage to find gaps
    • Write tests for edge cases, not just the happy path
    • Always re-run the full suite after a fix to check for regressions
  6. Challenge

    Conclusion

    Congratulations on completing this lab!

    Throughout this lab, you've had a chance to experiment with some of the key features that allow you to thoroughly test your ASP.NET applicaitons including:

    • Creating unit tests that isolate the tested code with mock objects.
    • Self-contained integration tests that allow the full application stack to be exercised by automatically starting the application to be tested.
    • Explored filtering and reporting capabilities to tune the test execution and output messages to match your needs.
    • Learned how to use a test-first approach to confirm application errors before correcting them.

    Feel free to continue to experiment in the lab environment to discover more about testing ASP.NET applications.

About the author

Michael VanSickle is an application architect in Akron, Ohio. He is a mechanical engineer by training and a software engineer by choice. He is passionate about learning new programming languages and user experience design.

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