C# 测试:单元测试、集成测试、端到端测试 — .NET 完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C# 测试:从单元测试到端到端测试——如何在 .NET 中构建高质量的检查架构



软件质量直接取决于测试体系。在 C# 和 .NET 生态系统中,存在一个成熟的测试金字塔:单元测试(unit)、集成测试(integration)和端到端测试(end-to-end)。本文将结合实际示例,逐一解析每个层级,展示应使用哪些库,并提供现成的代码模板。



1. 单元测试:代码稳定性的基础



单元测试用于独立于外部依赖(数据库、API、文件系统)检查单个方法、类或组件的功能。主要目标是在重构时快速发现回归问题。



C# 工具

  • NUnit — 经典框架,使用 [Test]、[TestCase] 属性。
  • xUnit — 由 NUnit 创建者开发的现代框架,在新项目中更受青睐。
  • Moq — 用于创建 mock 对象的库。
  • FluentAssertions — 用于编写可读性强的断言。


使用 xUnit 和 Moq 的单元测试示例

假设我们有一个折扣计算服务,它需要访问用户仓库:



public interface IUserRepository{    bool IsPremiumUser(int userId);}

public class DiscountService{ private readonly IUserRepository _userRepo; public DiscountService(IUserRepository userRepo) => _userRepo = userRepo;

public decimal CalculateDiscount(int userId, decimal amount) { if (_userRepo.IsPremiumUser(userId)) return amount * 0.9m; // 10% 折扣 return amount; }}

// 测试public class DiscountServiceTests{ [Fact] public void CalculateDiscount_ForPremiumUser_Returns90Percent() { // Arrange var mockRepo = new Mock<IUserRepository>(); mockRepo.Setup(r => r.IsPremiumUser(It.IsAny<int>())).Returns(true); var service = new DiscountService(mockRepo.Object);

// Act var result = service.CalculateDiscount(1, 100m);

// Assert Assert.Equal(90m, result); }}


建议: 在 xUnit 中使用 [Theory] 和 [InlineData] 进行参数化测试——这可以减少代码重复。



2. 集成测试:检查组件间的协作



集成测试用于检查您的模块如何与真实的外部系统(如数据库、消息队列、Web 服务)进行交互。与单元测试不同,这里不使用 mock——我们启动真实的运行环境。



库与方法

  • TestContainers — 直接从测试中启动 Docker 容器(PostgreSQL、SQL Server、Redis)。
  • WebApplicationFactory(来自 Microsoft.AspNetCore.Mvc.Testing)— 创建 ASP.NET Core 测试主机。
  • Respawn — 在测试之间清理数据库,无需重新创建容器。


使用 TestContainers 和 WebApplicationFactory 的集成测试示例

我们来验证 API 是否正确地将用户保存到 PostgreSQL:



public class UserApiIntegrationTests : IClassFixture<TestContainersFixture>{    private readonly HttpClient _client;    private readonly TestContainersFixture _fixture;

public UserApiIntegrationTests(TestContainersFixture fixture) { _fixture = fixture; var factory = new WebApplicationFactory<Program>() .WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { // 将真实连接字符串替换为容器连接字符串 services.RemoveAll<DbContextOptions<AppDbContext>>(); se

博客

书籍推荐