Orchard Core 中运行带程序上下文的单元测试

Orchard Core 中运行带程序上下文的单元测试

 

 Orchard Core 带有很多单元测试,使用 Xunit 单元测试框架,除了简单的直接调用待测试的方法,有一些复杂的测试是需要上下文的,甚至需要 Application 程序启动起来,Orchard Core 的例子中有一个基于 HTTP 的 Application 测试,但是其测试都是通过调用 HTTP API 执行的,测试 Controller 挺方便,但是测试 Service 等就麻烦了,而且测试往往是需要调用内部的一些方法的,所以 HTTP API 测试适用范围有限。

 

`WebApplicationFactory` can only test by http method, could not direct call Application’s component, like do some Session.Query() then direct call some method to do a complex test.

 

所以自己做了个能够启动 Application 且在 Application 上下文内执行测试的单元测试基类和辅助方法。使用方便,继承即可使用,然后你就可以像在 Orchard Core 内部写代码一样,去调用各种 Service、Query 进行测试啦。

 

由于是从我给 Orchard Core 团队提的 issue 里面整理拷贝而来,中英文混合,将就着看,主要把我的实现代码分享,方便有需要的人。

 

 public class AppTestBase<TFixture> : IClassFixture<TFixture> where TFixture : class, IApplicationStartupFixture 
{
public readonly TFixture Application; public AppTestBase(TFixture application) { this.Application = application; } protected T GetService<T>() where T : class { return this.Application.ServiceProvider.GetService<T>(); } protected T GetRequiredService<T>() where T : class { return this.Application.ServiceProvider.GetRequiredService<T>(); } protected async Task RunInShellScopeAsync(Func<ShellScope, Task> execute) { var shellContextFactory = GetRequiredService<IShellContextFactory>(); IShellHost shellHost = GetRequiredService<IShellHost>(); using (var shell = await shellContextFactory.CreateDefaultShellContext()) using (var shellScope = shell.CreateScope()) { var httpContextAccessor = shellScope.ServiceProvider.GetService<IHttpContextAccessor>(); httpContextAccessor.HttpContext = shellScope.ShellContext.CreateHttpContext(); await shellScope.UsingAsync(execute); } } protected T CreateController<T>(ShellScope shellScope, HttpContext httpContext) { var controllerActivatorProvider = shellScope.ServiceProvider.GetService<IControllerActivatorProvider>(); var controllerContext = new ControllerContext() { HttpContext = httpContext, }; var controllerObj = (T) controllerActivatorProvider.CreateActivator( new ControllerActionDescriptor() {ControllerTypeInfo = (TypeInfo) typeof(T),}) .Invoke(controllerContext); return controllerObj; } }

 

add database setting in ShellSettings (required):

    settings["DatabaseProvider"] ="SqlConnection";
    settings["ConnectionString"] = "Server=localhost;Database=xxx;User Id=sa;Password=xxxxxxx";
    settings["TablePrefix"] = "xxx";

 

    
public static class TestShellContextFactoryExtensions
{
    internal static Task<ShellContext> CreateDefaultShellContext(this IShellContextFactory shellContextFactory)
    {
            var settings = new ShellSettings()
            {
                Name = ShellHelper.DefaultShellName,
                State = TenantState.Running
            };
            
        settings["DatabaseProvider"] ="SqlConnection";
        settings["ConnectionString"] = "Server=localhost;Database=xxx;User Id=sa;Password=xxxxxxx";
        settings["TablePrefix"] = "xxx";
    
            return shellContextFactory.CreateDescribedContextAsync(settings, new ShellDescriptor()
            {
                Features = new List<ShellFeature>()
                {
                    new ShellFeature("Application.Default"),
                    new ShellFeature("OrchardCore.Setup"),
                    new ShellFeature("Operational"),
                },
                Parameters = new List<ShellParameter>(),
            });
            // return shellContextFactory.CreateShellContextAsync(settings);
    }

}

 

 

 

An helper to create `HttpContext`, and set set `shell.RequestServices` to `HttpContext`.

 

    public static HttpContext CreateHttpContext(this ShellContext shell)
    {
        var settings = shell.Settings;

        var context = new DefaultHttpContext();
         
                // set shell.RequestServices to context
        context.RequestServices = shell.ServiceProvider;
        OrchardCore.Modules.HttpContextExtensions.UseShellScopeServices(context);

        var urlHost = settings.RequestUrlHost?.Split('/',
            StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();

        context.Request.Host = new HostString(urlHost ?? "localhost");

        if (!String.IsNullOrWhiteSpace(settings.RequestUrlPrefix))
        {
            context.Request.PathBase = "/" + settings.RequestUrlPrefix;
        }

        context.Request.Path = "/";
        context.Items["IsBackground"] = true;

        context.Features.Set(new ShellContextFeature
        {
            ShellContext = shell,
            OriginalPathBase = String.Empty,
            OriginalPath = "/"
        });

        return context;
    }


 

使用的例子(先继承基类):

    [Fact]
    public async Task InAppRuntimeTest() {
        await RunInShellScopeAsync(async shellScope =>
        {
            var session = shellScope.ServiceProvider.GetService<ISession>();
            Assert.NotNull(session);

            var controllerObj =
                    CreateController<XxxxxController>(shellScope, shellScope.ShellContext.CreateHttpContext());

            var result = await controllerObj.Index(new XxxxModel(){});

            Assert.NotNull(result);
        });
    }

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119608.html原文链接:https://javaforall.net

(0)
上一篇 2021年11月24日 下午1:00
下一篇 2021年11月24日 下午2:00


相关推荐

  • 什么是oracle数据库实例_oracle库和实例区别

    什么是oracle数据库实例_oracle库和实例区别一、数据库(Database)  数据库是一个数据的集合,不仅是指物理上的数据,也指物理、存储及进程对象的一个组合。Oracle是关系型数据库管理系统(RDBMS)。二、实例(Instance)  数据库实例(也称为服务器Server)就是用来访问一个数据库文件集的一个存储结构及后台进程的集合。它使一个单独的数据库可以被多个实例访问(也就是ORACLE并行服务器–

    2022年8月30日
    5
  • 学生成绩管理系统数据库设计–MySQL/SQL Server[通俗易懂]

    学生成绩管理系统数据库设计–MySQL/SQL Server[通俗易懂]MySQL/SQLServer数据库设计(学生成绩管理系统)设计大纲1.项目背景及需求分析1.1项目背景1.2 需求分析1.2.1 信息需求1.2.2 功能需求1.2.3 安全性与完整性需求2. 概念结构设计2.1抽象出系统实体2.2全局E-R图3. 逻辑结构设计3.1关系模式3.2函数依赖识别3.3范式4. 物理设计和实施4.1数据库及表创建4.2表数据增删改查测试4.3创建视图4.4创建函数4.5创建存储过程4.6创建触发器

    2022年5月19日
    60
  • Java修饰符作用域

    Java修饰符作用域Java 修饰符作用域

    2026年3月11日
    4
  • 网卡offload功能介绍

    网卡offload功能介绍offload 是将本来该操作系统进行的一些数据包处理 如 TCP 分段 IP 分片 重组 checksum TCP 协议处理等 放到网卡硬件中去做 降低系统 CPU 消耗的同时 提高处理的性能 普通网卡用软件方式进行一系列 TCP IP 相关操作 因此 会在三个方面增加服务器的负担 这三个方面是 数据复制 协议处理和中断处理 1 TSO TCP Segmentation Offload 将 TCP 分段工作交由网卡驱动执行 该特性需要网卡硬件支持 使能 TSO 后 操作系统可以将一个不超过

    2026年3月19日
    2
  • 文心AI电脑版

    文心AI电脑版

    2026年3月12日
    2
  • 张予彤,出任月之暗面总裁

    张予彤,出任月之暗面总裁

    2026年3月12日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号