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

在ServiceStack OrmLite MVC应用中测试/模拟AuthUserSession的问题

ServiceStack MVC控制器单元测试中AuthUserSession空引用问题

问题背景

现有基于ServiceStack OrmLite的MVC应用,添加控制器测试时,其他依赖注入的模拟均正常,但AuthUserSession始终抛出空引用异常。所有控制器都继承自基础控制器_Controller,其中包含:

public MyAuthUserSession AuthUserSession => SessionAs<MyAuthUserSession>();

MyAuthUserSession继承自AuthUserSession,包含自定义权限检查方法,控制器中会通过该属性做权限校验,例如:

model.CanEdit = AuthUserSession.HasEntityPermission(PermissionType.Update, PermissionEntity.MyEntity);

已尝试但无效的方案

  • 配置测试AppHost:完全照搬生产环境的AuthFeature配置,但会话始终未被填充

    public class TestAppHost : AppHostBase
    {
        public TestAppHost() : base("Test Service", typeof(LocationsService).Assembly) { }
    
        public override void Configure(Container container)
        {
            Plugins.Add(new AuthFeature(() => new MyAuthUserSession(), new IAuthProvider[] { new BasicAuthProvider() })
            {
                IncludeAssignRoleServices = false,
                IncludeAuthMetadataProvider = false,
                IncludeRegistrationService = false,
                GenerateNewSessionCookiesOnAuthentication = false,
                DeleteSessionCookiesOnLogout = true,
                AllowGetAuthenticateRequests = req => true
            });
        }
    }
    
  • 手动保存会话:通过AuthenticateService保存测试会话,但与控制器的SessionAs调用不关联

    var authService = appHost.Container.Resolve<AuthenticateService>();
    var session = new MyAuthUserSession();
    authService.SaveSessionAsync(session).Wait();
    
  • 直接注册IAuthSession实例:在AppHost中注册会话实例,无任何效果

    TestMode = true;
    container.Register<IAuthSession>(new MyAuthUserSession { UserAuthId = "1" });
    
  • 修改ControllerContext.HttpContext:尝试往请求项中添加会话,未成功

关键差异发现

API服务中(继承自Service)仅需注册IAuthSession即可正常获取会话,但MVC控制器(继承自ServiceStackController)同样操作无效。简化测试代码后,即使使用空控制器+基础配置的AppHost,调用SessionAs仍抛出空引用:

简化测试代码

TestAppHost配置:

public class TestAppHost : BasicAppHost
{
    public TestAppHost() : base(typeof(LocationsService).Assembly) { }

    public override void Configure(Container container)
    {
        container.Adapter = new UnityIocAdapter(Repository.Container.Instance);
        Plugins.Add(new AuthFeature(() => new AuthUserSession(),
    new IAuthProvider[] {
        new BasicAuthProvider(),       // HTTP Basic Auth登录
        new CredentialsAuthProvider(), // 用户名密码表单登录
    }));

        container.Register<ICacheClient>(new MemoryCacheClient());
        var userRepo = new InMemoryAuthRepository();
        container.Register<IAuthRepository>(userRepo);
        container.Register<IAuthSession>(new AuthUserSession());
    }
}

空控制器:

public class EmptyController: ServiceStackController
{
    public EmptyController() {}

    public AuthUserSession AuthUserSession => SessionAs<AuthUserSession>();
}

测试调用代码:

_appHost = new TestAppHost();
_appHost.Init();
var contr = _appHost.Resolve<EmptyController>();
var session = contr.AuthUserSession; // 此处抛出空引用异常

异常堆栈跟踪

at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at ServiceStack.Host.NetCore.NetCoreRequest.TryResolve[T]()
at ServiceStack.ServiceStackHost.GetCacheClient(IRequest req)
at ServiceStack.ServiceStackProvider.get_Cache()
at ServiceStack.ServiceStackProvider.SessionAs[TUserSession]()
at ServiceStack.Mvc.ServiceStackController.SessionAs[TUserSession]()
at WebApplication.Controllers._Controller.get_AuthUserSession() in _Controller.cs:line 93
at WebApplication.Controllers.MyController.Common(PageAction action, MyDataModel model) in MyController.cs:line 288
at WebApplication.Controllers.MyController.Show(Int64 id) in MyController.cs:line 157
at WebApplication.UnitTests.Controllers.MyControllerTests.Show_WithReadPrivileges_ReturnsExpectedSettingValue() in MyControllerTests.cs:line 115

核心需求

由于是遗留应用,无法修改AuthUserSession属性(全项目约1000处引用,重构成本极高),且该属性为常规属性,无法用NSubstitute模拟返回值。需要找到一种无需大规模重构的方式,让ServiceStackController的SessionAs<MyAuthUserSession>()返回指定的测试会话。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:53:15