_currentUser = Substitute.For<ICurrentUser>();
这是 NSubstitute(一个 .NET 单元测试 mock 框架)中的标准用法,用来“创建一个假的 ICurrentUser 实例”。
下面详细解释它的逻辑。
✅ 到底发生了什么?
Substitute.For<T>() 的作用是:
创建一个可替代(mock)的 T 类型实例,这个实例可以记录调用、返回你设定的值、并用于断言。
所以:
_currentUser = Substitute.For<ICurrentUser>();
等价于:
“创建一个假的 ICurrentUser 对象,它实现所有 ICurrentUser 上的方法和属性,但行为都由我控制。”
也就是 mock / stub / fake。
🔍 这个 fake ICurrentUser 有什么能力?
它默认:
- 所有属性、方法都会返回 默认值(如 null、0、false)。
- 它可以记录“谁调用了我”。
- 你可以给它设定返回值。
- 你可以检查它是否收到某个调用。
例如:
✔️ 设定值
_currentUser.Id.Returns(Guid.Parse("..."));
_currentUser.UserName.Returns("John");
✔️ 测试某个方法是否调用过 ICurrentUser
await someService.DoWork();
_currentUser.Received().Id; // 断言 Id 被访问过
✔️ 设定更复杂的行为
_currentUser.FindClaim("role").Returns(new Claim("role", "admin"));
🧠 为什么要这样写?
在 ABP 或 ASP.NET Core 中,ICurrentUser 是依赖注入来的,不可能在单元测试中依赖真实用户。
测试应该在无用户登录也能运行,或者测试“模拟登录”。
所以 NSubstitute 提供了这种 fake 来模拟各种情况:
例:模拟当前用户已登录:
_currentUser.IsAuthenticated.Returns(true);
_currentUser.UserName.Returns("Tester");
例:模拟当前用户没有权限:
_currentUser.GetId().Returns((Guid?)null);
📝 总结一句话
Substitute.For<ICurrentUser>()会创建一个假的 ICurrentUser 对象,用于单元测试时替换真实的用户上下文,让你可以自由设置当前用户的各种属性与行为,并可断言调用状况。