ASP.NET Core 2.0 Web API:带授权的InvitationsController单元测试咨询
嘿,针对你在ASP.NET Core 2.0 Web API里写的带[Authorization]特性的InvitationsController,我给你梳理几个实用的单元测试思路,都是实际项目里常用的:
1. 模拟认证上下文,绕过授权检查
单元测试的核心是验证控制器的业务逻辑,而非授权机制本身。所以我们可以通过给控制器设置一个模拟的认证用户上下文,让它认为当前请求已经通过授权校验。
首先,你需要用Moq这类 mocking 框架来模拟控制器的依赖项(IInvitationManager、IMapper、UserManager<MyAppUser>),然后给控制器的ControllerContext设置一个带有认证信息的HttpContext:
// 先封装一个获取Mock UserManager的方法,因为它的构造参数比较多 private static Mock<UserManager<MyAppUser>> GetMockUserManager() { var userStoreMock = new Mock<IUserStore<MyAppUser>>(); return new Mock<UserManager<MyAppUser>>( userStoreMock.Object, null, null, null, null, null, null, null, null); } // 初始化控制器和依赖 var mockInvitationManager = new Mock<IInvitationManager>(); var mockMapper = new Mock<IMapper>(); var mockUserManager = GetMockUserManager(); var controller = new InvitationsController( mockInvitationManager.Object, mockMapper.Object, mockUserManager.Object, null); // 如果当前测试用不到IJobManager,传null或Mock对象都行 // 设置认证用户上下文,模拟已登录状态 controller.ControllerContext = new ControllerContext { HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal(new ClaimsIdentity(new[] { // 添加必要的声明,比如用户ID、角色(如果授权需要特定角色的话) new Claim(ClaimTypes.NameIdentifier, "test-user-123"), new Claim(ClaimTypes.Role, "InvitationViewer") }, "mock-authentication-scheme")) } };
2. 编写具体的业务逻辑测试用例
比如针对你提到的GetInvitationByCode方法,我们可以写测试用例验证“合法邀请码返回正确结果”的场景:
[Fact] public async Task GetInvitationByCode_WithValidCode_ReturnsOkResult() { // Arrange var testInvitationCode = "VALID-INVITE-123"; var mockInvitation = new Invitation { Id = 5, Code = testInvitationCode }; var mockInvitationDto = new InvitationDto { Id = 5, Code = testInvitationCode }; var mockInvitationManager = new Mock<IInvitationManager>(); mockInvitationManager .Setup(m => m.GetInvitationByCodeAsync(testInvitationCode)) .ReturnsAsync(mockInvitation); var mockMapper = new Mock<IMapper>(); mockMapper .Setup(m => m.Map<InvitationDto>(mockInvitation)) .Returns(mockInvitationDto); var mockUserManager = GetMockUserManager(); var controller = new InvitationsController( mockInvitationManager.Object, mockMapper.Object, mockUserManager.Object, null); // 设置认证上下文 controller.ControllerContext.HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, "test-user-123") })) }; // Act var actionResult = await controller.GetInvitationByCode(testInvitationCode); // Assert var okResult = Assert.IsType<OkObjectResult>(actionResult); var returnedDto = Assert.IsType<InvitationDto>(okResult.Value); Assert.Equal(testInvitationCode, returnedDto.Code); }
3. 测试未授权场景(可选)
如果你想验证[Authorization]特性确实在生效,可以写一个测试用例模拟未登录用户的请求,断言返回UnauthorizedResult:
[Fact] public async Task GetInvitationByCode_WithoutAuthentication_ReturnsUnauthorized() { // Arrange var mockInvitationManager = new Mock<IInvitationManager>(); var mockMapper = new Mock<IMapper>(); var mockUserManager = GetMockUserManager(); var controller = new InvitationsController( mockInvitationManager.Object, mockMapper.Object, mockUserManager.Object, null); // 不设置HttpContext.User,模拟未登录状态 // Act var actionResult = await controller.GetInvitationByCode("any-code"); // Assert Assert.IsType<UnauthorizedResult>(actionResult); }
注意事项
- 如果你用的是
[Authorize](可能你打错成[Authorization]了?ASP.NET Core里标准的授权特性是[Authorize]),上面的方法同样适用。 - 所有依赖项都要根据测试场景做合适的Mock设置,避免空引用异常。
- 如果你需要测试更复杂的授权规则(比如角色、策略),可以在Claims里添加对应的声明来模拟。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

