在C#开发中,单元测试是保障代码质量的重要手段。而为了隔离被测代码与其他依赖项(如数据库、网络服务等),我们常常会用到测试替身(Test Doubles)。常见的测试替身包括 Stub、Mock 和 Fake。很多初学者容易混淆这三者,本文将用通俗易懂的方式讲解它们的区别,并通过实际C#代码示例帮助你掌握使用场景。
测试替身是在测试过程中用来替代真实依赖的对象。它们不会执行真实逻辑(比如连接数据库),而是返回预设的数据或行为,从而让测试更快速、可靠和可重复。
Stub 是一种最简单的测试替身。它只负责提供预设的返回值,不验证调用是否发生,也不关心方法被调用了多少次。
适用场景:当你只需要控制依赖的输出,而不关心其交互细节时。
// 定义接口public interface IEmailService{ bool SendEmail(string to, string subject);}// Stub 实现class EmailServiceStub : IEmailService{ public bool SendEmail(string to, string subject) { // 总是返回 true,模拟发送成功 return true; }}// 被测类public class UserManager{ private readonly IEmailService _emailService; public UserManager(IEmailService emailService) { _emailService = emailService; } public bool RegisterUser(string email) { // 注册逻辑... var success = _emailService.SendEmail(email, "Welcome!"); return success; }}// 测试代码[Fact]public void RegisterUser_ShouldReturnTrue_WhenEmailSent(){ var stub = new EmailServiceStub(); var userManager = new UserManager(stub); var result = userManager.RegisterUser("test@example.com"); Assert.True(result); // 只验证结果,不验证 SendEmail 是否被调用} Mock 不仅能提供预设行为,还能验证方法是否被调用、调用次数、参数是否正确等。它关注的是交互行为。
通常我们会借助像 Moq 这样的 mocking 框架来创建 Mock 对象。
// 使用 Moq 创建 Mock[Fact]public void RegisterUser_ShouldCallSendEmail_Once(){ var mock = new Mock<IEmailService>(); mock.Setup(x => x.SendEmail("test@example.com", "Welcome!")) .Returns(true); var userManager = new UserManager(mock.Object); userManager.RegisterUser("test@example.com"); // 验证 SendEmail 被调用了一次 mock.Verify(x => x.SendEmail("test@example.com", "Welcome!"), Times.Once);} Fake 是一个具有完整但简化实现的替代对象。它不是“空壳”,而是用更轻量、更快的方式模拟真实依赖,比如用内存数据库代替 SQL Server。
Fake 通常用于集成测试,但也可用于单元测试。
// 假的用户仓库(使用内存字典代替数据库)public class FakeUserRepository : IUserRepository{ private readonly Dictionary _users = new(); public void Add(User user) { _users[user.Email] = user; } public User? GetByEmail(string email) { return _users.TryGetValue(email, out var user) ? user : null; }}// 测试[Fact]public void UserService_AddUser_ShouldStoreInFakeRepo(){ var fakeRepo = new FakeUserRepository(); var service = new UserService(fakeRepo); service.AddUser("alice@example.com", "Alice"); var user = fakeRepo.GetByEmail("alice@example.com"); Assert.NotNull(user); Assert.Equal("Alice", user.Name);} | 类型 | 目的 | 是否验证调用 | 典型用途 |
|---|---|---|---|
| Stub | 提供预设返回值 | 否 | 控制输入,简化依赖 |
| Mock | 验证交互行为 | 是 | 测试方法是否被正确调用 |
| Fake | 提供轻量级完整实现 | 通常不验证(但可查状态) | 替代复杂依赖(如数据库) |
掌握 C#测试替身 的使用,是写出高质量 C#单元测试 的关键一步。无论是 Stub与Mock区别,还是 Fake对象 的应用场景,理解它们能让你的测试更精准、更高效。
提示:在实际项目中,推荐使用 Moq、NSubstitute 等框架来创建 Mock/Stub,避免手写大量样板代码。
本文由主机测评网于2025-12-27发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20251213175.html