惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
博客园 - 【当耐特】
WordPress大学
WordPress大学
爱范儿
爱范儿
美团技术团队
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
量子位
Hugging Face - Blog
Hugging Face - Blog
B
Blog RSS Feed
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
博客园 - 叶小钗
GbyAI
GbyAI
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Full Disclosure
G
Google Developers Blog
D
Docker
T
Tailwind CSS Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
T
The Blog of Author Tim Ferriss
B
Blog
博客园 - 三生石上(FineUI控件)
博客园 - Franky
H
Help Net Security
MyScale Blog
MyScale Blog
U
Unit 42
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
L
LangChain Blog
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
[.NET] Aspire, Simplifying Local Development Environment and Testing.
Steven Hoang · 2026-05-18 · via DEV Community

Steven Hoang

Starting a new project is both exciting and challenging, especially when it comes to configuring the development environment. Many projects require a mix of technologies, which can lead to time-consuming setup and potential errors. .NET Aspire simplifies this process by offering a framework that helps developers set up a consistent and efficient environment across various projects.

With .NET Aspire, We can create a ready-to-run local environment that integrates seamlessly with Docker, allowing the development team to focus on coding without worrying about complex setup requirements. It supports smooth integration with containers, making it easier to handle dependencies and ensuring that our local environment closely mirrors the development/staging environment setup.

In addition to simplifying environment setup, this guide walks us through writing robust integration tests. These tests ensure all components work well together and catch potential issues early in the development process. We'll also learn how to incorporate these tests into a continuous integration (CI) pipeline, ensuring the code is consistently validated and error-free before it reaches production.

Why .NET Aspire?

.NET Aspire is designed to improve the experience of building .NET cloud-native applications. It provides a consistent, opinionated set of tools and patterns that help to build and run distributed apps. .NET Aspire assists with:

  • Orchestration: Features for running and connecting multi-project applications and their dependencies in local development environments.
  • Integrations: NuGet packages for commonly used services, such as Redis or PostgreSQL, with standardized interfaces ensuring they connect consistently and seamlessly with the app.
  • Tooling: Project templates and tooling experiences for Visual Studio, Visual Studio Code, and the dotnet CLI to help to create and interact with .NET Aspire projects.

Table of Contents

  1. Why .NET Aspire?
  2. Setting Up the Local Environment
  3. Hosting with Aspire
  4. .NET Aspire for Testing
  5. Running Tests on Azure DevOps
  6. Conclusion

Setting Up the Local Environment

Let's start by creating a simple API project and hosting it with .NET Aspire.

Prerequisites

  • .NET 8 SDK or later
  • Docker Desktop installed and running
  • Aspire workload installed: Install the Aspire workload using the following command:
  dotnet workload install aspire

Enter fullscreen mode Exit fullscreen mode

Creating an API Project

Assuming we already have a simple API that utilizes the following technologies:

  • MediatR: A library used to implement the command and response pattern at the API level. It helps decouple request handling logic from controllers, making the code more modular and easier to maintain.
  • Entity Framework Core (EF Core): An Object-Relational Mapper (ORM) used to manage database access.
  • PostgreSQL: Used as the database to store and manage the application's data.

This API has the following endpoints, as displayed in the Swagger UI:

Api

Aspire Templates Explanation

Aspire provides several project templates to help to get started quickly with different aspects of application development and testing:

  • App Host: The primary template for creating an Aspire hosting project. It sets up the necessary infrastructure to host the application and its dependencies.
  • Service Defaults: Configures essential services for the application, such as OpenTelemetry for distributed tracing, DefaultHealthChecks for monitoring service health, and RequestTimeouts to manage request durations. While optional, it's highly recommended for applications hosted on Aspire to ensure robust monitoring and orchestration management.
  • Test Project (MSTest): Sets up a project for unit testing using the MSTest framework.
  • Test Project (NUnit): Sets up a project for unit testing using the NUnit framework.
  • Test Project (xUnit): Sets up a project for unit testing using the xUnit framework.

AspireTemplates

Hosting with Aspire

To host the API above with its dependencies with Aspire, follow these steps:

1. Create Aspire.Host

First, create a new project named Aspire.Host using the App Host template provided by .NET Aspire.

2. Add PostgreSQL Support

Next, install the Aspire PostgreSQL hosting package to add PostgreSQL support to this project.

dotnet add package Aspire.Hosting.PostgreSQL

Enter fullscreen mode Exit fullscreen mode

Note: Refer to the .NET Aspire GitHub repository for a full list of hosting components supported by Aspire.

3. Aspire Host with Config as Code

Open Program.cs in the Aspire.Host project and configure the DistributedApplication as shown:

inline

Explanation:

  • AddPostgres("postgres"): This adds a PostgreSQL service to the Aspire hostwith named as "postgres".
  • AddDatabase("Db"): This sets up a database named "Db". This database will be used by the API.
  • AddProject("api"): This method adds our API project to the Aspire host named as "api".
  • WithReference(postgres): This references the database service to the API project. It sets up the connection string configuration for the API to connect to the PostgreSQL database.
  • WaitFor(postgres): This ensures that the PostgreSQL resource is fully up and running before the API project starts. This is a new functionality added in Aspire 9, ensuring that the API only starts after the database is ready.

4. EF Core Database Migration

Automating database migrations is important when using EF Core to ensure consistency across environments. While we won't discuss the details here, you can refer to the EF Core Migrations guide compatible with .NET Aspire.

Here is a sample code to run the EfCore migration as a background job when the API started:

Example DbMigrationJob.cs

inline

5. Aspire Host Dashboard

Run the Aspire.Host project. The dashboard will display all running components.

Dashboard

Note:
If you are migrating from Aspire version 8 to version 9, ensure that the <Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0"/> element is added to the project file. This ensures compatibility and leverages the latest features and improvements in Aspire 9.

Example Aspire.Host.csproj [inline](https://github.com/baoduy/sample-aspire-dotnet-testing/blob/main/Aspire.Host/Aspire.Host.csproj#1-100)

.NET Aspire for Testing

Integration tests ensure that different parts of the application work together correctly. However, writing and running them on CI/CD pipelines can be challenging and time-consuming. .NET Aspire simplifies this process by handling much of the setup for us.

1. Create Aspire.Tests

Create a new test project named Aspire.Tests using the Test Project (xUnit) template provided by .NET Aspire. This template sets up the necessary scaffolding for integration tests using xUnit.

Note:
Similar to Aspire.Host project. Ensure that the <Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0"/> element is added to the project file.

Example Aspire.Tests.csproj [inline](https://github.com/baoduy/sample-aspire-dotnet-testing/blob/main/Aspire.Tests/Aspire.Tests.csproj#1-100)

2. ApiFixture Class

The ApiFixture class sets up the necessary environment for integration tests. It extends WebApplicationFactory<Api.Program> and implements IAsyncLifetime to manage the lifecycle of the test environment.

inline

Explanation:

The ApiFixture class is responsible for:

  • Setting up a PostgreSQL server resource.
  • Configuring the host with the necessary connection strings.
  • Ensuring the database is created and testing data prepared before tests run.
  • Starting and stopping the application host.
  • Cleaning up resources after tests are completed.

3. Test Cases Class

The ProductEndpointsTests class contains integration tests for the product endpoints of the API. It uses the ApiFixture to set up the test environment and HttpClient to make requests to the API.

inline

Explanation:

The ProductEndpointsTests class is responsible for testing the CRUD of the product endpoints. It ensures that:

  • Creating a product works correctly and returns a valid product ID.
  • Retrieving a product returns the expected product details.
  • Updating a product successfully applies the changes and returns the appropriate status.
  • Deleting a product removes it from the database and returns the correct status code.

4. Testing Results

Here are the reports on Azure DevOps after the pipeline ran successfully.

  • Test Case Results:

The test case results show the outcome of each executed test.

TestCasesResults

  • Coverage Results:

Code coverage results provide insights into how much of the codebase is being tested.

TestCoverageResults

Running Tests on Azure DevOps

1. Configuring the Pipeline

To automate testing and code coverage collection, let's set up a continuous integration (CI) pipeline using Azure DevOps.

In the Azure DevOps project, create a new pipeline that builds the code, runs tests, and collects code coverage data.

Here is an example of what our azure-pipelines.yml file might look like.

inline

Explanation:

  • UseDotNet@2: Ensures that the correct .NET SDK is installed on the build agent.
  • Install Aspire Workload: Installs the Aspire workload needed for the project.
  • Build Projects: Builds all the projects specified by the RestoreBuildProjects variable.
  • Run Tests and Collect Code Coverage: Executes the tests in the projects specified by the TestProjects variable and collects code coverage data.

Note: Ensure that the YAML file includes the UseDotNet@2 task to specify the required .NET SDK version.

Running the Pipeline

Save the pipeline configuration and run it. Monitor the build process to ensure all steps complete successfully.

After the pipeline completes, the test results and code coverage reports should be appeared in Azure DevOps.

  1. Test Results:

Displays which tests passed or failed.

devops-test-results

  1. Code Coverage:

Provides detailed information about which parts of the code were tested.

devops-test-coverage

Note: The initial code coverage might be lower than expected. For example, you might see an overall coverage of 23.89%, even though the API component itself has 88.14% coverage. This discrepancy occurs because the coverage report includes all libraries, those not part of the API project.

Improving Code Coverage Reports

To produce a more focused and insightful code coverage report, we can adjust the settings to concentrate on the pertinent components of the project.

1. Add the coverlet.collector NuGet Package

Coverlet is a versatile, cross-platform library designed for code coverage analysis. It supports a variety of code coverage formats and allows for extensive customization options.

Ensure that the coverlet.collector package is added to every testing project in order to generate and compile comprehensive code coverage reports.

dotnet add package coverlet.collector --version latest

Enter fullscreen mode Exit fullscreen mode

  1. Creating the Coverage Filtering File:

Create a file named coverage.runsettings in the project root with the appropriate configuration.

inline

Explanation:

  • The <Include> section specifies which assemblies to include in the code coverage report. In this case, [Api*]* includes all assemblies starting with "Api".
  • The <Exclude> section can be used to exclude specific assemblies or classes.
  1. Updating the Pipeline Configuration:

Modify the azure-pipelines.yml file to use the coverage.runsettings file and publish the code coverage results.

# ... previous configuration ...

# Run tests with coverage filtering
- task: DotNetCoreCLI@2
  displayName: "Test with Coverage Filtering"
  inputs:
    command: "test"
    projects: "$(TestProjects)"
    arguments: '--configuration $(BuildConfiguration) --settings coverage.runsettings --collect "XPlat Code Coverage"'

# Publish the code coverage results to Azure DevOps
- task: PublishCodeCoverageResults@2
  inputs:
    summaryFileLocation: "$(Agent.TempDirectory)/**/coverage.cobertura.xml"

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Run Tests with Coverage Filtering: Executes tests using the coverage.runsettings file to filter the code coverage data.
  • Publish Code Coverage Results: Publishes the code coverage results to Azure DevOps for easy visualization.
  1. Review the Enhanced Coverage Report:

After running the updated pipeline, We should see an improved code coverage report that focuses on the relevant parts of the project. The coverage results will now provide detailed insights at the class level using the XPlat format.

devops-test-coverage-with-filter

Conclusion

By utilizing .NET Aspire and Docker, we can create a consistent, isolated environment that streamlines not just Entity Framework integration testing but the entire development lifecycle. .NET Aspire offers a flexible to config as code and sharing ready-to-run environment to all the development teams.

References

Thank You

Thank for taking the time to read this guide! I hope it has been helpful, feel free to explore further, and happy coding! 🌟✨

Steven
GitHub