You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试Razor视图渲染:验证TextPosts展示权限逻辑

测试Razor视图内容权限控制的解决思路

核心目标

验证未登录用户访问页面时,非会员受限的TextPosts全部正常展示,会员专属的TextPosts完全不显示,同时标签的权限控制逻辑也符合预期。


步骤1:搭建InMemory测试环境与模拟数据

配置InMemory数据库

使用EF Core的InMemory数据库模拟真实仓储,确保测试数据隔离且无需真实数据库:

// 测试类中配置服务集合
var services = new ServiceCollection();
services.AddDbContext<AppDbContext>(options => 
    options.UseInMemoryDatabase("TestTextsDb"));
// 注册仓储实现(适配你的项目仓储接口)
services.AddScoped<ITextPostRepository, TextPostRepository>();
services.AddScoped<ITagRepository, TagRepository>();
// 添加Identity服务用于模拟登录状态
services.AddIdentity<IdentityUser, IdentityRole>()
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

插入测试数据

在测试初始化时,插入两类符合权限规则的测试数据:

using var scope = services.BuildServiceProvider().CreateScope();
var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

// 1. 非会员标签+对应TextPost(RestrictedToMembers=false)
var publicTag = new Tag
{
    Name = "Public",
    TagManagement = new TagManagement { RestrictedToMembers = false, IsMeeting = false }
};
context.Tags.Add(publicTag);
context.TextPosts.Add(new TextPost
{
    Heading = "公开文章标题",
    Author = "测试作者",
    PublishedDate = DateTime.Now,
    PageTitle = "公开文章副标题",
    FeaturedImageUrl = "test.jpg",
    Tag = publicTag
});

// 2. 会员专属标签+对应TextPost(RestrictedToMembers=true)
var memberTag = new Tag
{
    Name = "MemberOnly",
    TagManagement = new TagManagement { RestrictedToMembers = true, IsMeeting = false }
};
context.Tags.Add(memberTag);
context.TextPosts.Add(new TextPost
{
    Heading = "会员专属文章标题",
    Author = "会员作者",
    PublishedDate = DateTime.Now,
    PageTitle = "会员专属副标题",
    FeaturedImageUrl = "member.jpg",
    Tag = memberTag
});

await context.SaveChangesAsync();

步骤2:模拟未登录用户,测试视图渲染

使用bUnit(专门用于测试Razor页面/组件的工具)渲染视图并验证DOM:

模拟未登录状态

Mock SignInManager,让IsSignedIn(User)返回false:

// 初始化bUnit测试上下文
using var ctx = new TestContext();
// 注册Mock的SignInManager
var mockSignInManager = new Mock<SignInManager<IdentityUser>>();
mockSignInManager.Setup(s => s.IsSignedIn(It.IsAny<ClaimsPrincipal>())).Returns(false);
ctx.Services.AddSingleton(mockSignInManager.Object);

// 获取PageModel并执行OnGet逻辑
var pageModel = ctx.Services.GetRequiredService<TextsModel>();
await pageModel.OnGet();

// 渲染Razor页面
var component = ctx.RenderComponent<Texts>(parameters => 
    parameters.Add(p => p.Model, pageModel));

断言验证核心逻辑

// 验证公开文章的元素存在
component.Find("h2:contains('公开文章标题')").Should().NotBeNull();
component.Find("p:contains('测试作者')").Should().NotBeNull();

// 验证会员专属文章的元素完全不渲染
component.FindAll("h2:contains('会员专属文章标题')").Should().BeEmpty();
component.FindAll("p:contains('会员作者')").Should().BeEmpty();

// 验证标签权限:公开标签显示,会员标签不显示
component.Find("span.badge:contains('Public')").Should().NotBeNull();
component.FindAll("span.badge:contains('MemberOnly')").Should().BeEmpty();

步骤3:(可选)验证登录用户的权限逻辑

为确保权限控制逻辑完整,可补充登录场景测试:

// 修改Mock,模拟用户已登录
mockSignInManager.Setup(s => s.IsSignedIn(It.IsAny<ClaimsPrincipal>())).Returns(true);
var component = ctx.RenderComponent<Texts>(parameters => 
    parameters.Add(p => p.Model, pageModel));

// 验证会员专属内容正常显示
component.Find("h2:contains('会员专属文章标题')").Should().NotBeNull();
component.Find("span.badge:contains('MemberOnly')").Should().NotBeNull();

关键注意事项

  • 确保测试数据避开IsMeeting=true的标签/文章,匹配后端OnGet方法的过滤逻辑
  • 使用bUnit可直接操作渲染后的DOM,比手动解析HTML更可靠
  • 补充分页场景测试(比如传入page=2参数),确保分页后权限控制依然生效

内容的提问来源于stack exchange,提问作者mathdx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:47:23