zoukankan      html  css  js  c++  java
  • 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);
            });
        }
  • 相关阅读:
    stm32 oled学习
    PWM输出配置步骤
    IIC通信笔记
    运算放大器原理
    stm32跑马灯实现及蜂鸣器实验
    一个字节多少位
    pyQT编写界面调用摄像头
    PAT Advanced 1151 LCA in a Binary Tree (30) [树的遍历,LCA算法]
    PAT Advanced 1143 Lowest Common Ancestor (30) [二叉查找树 LCA]
    PAT Advanced 1147 Heaps (30) [堆,树的遍历]
  • 原文地址:https://www.cnblogs.com/darklx/p/13710491.html
Copyright © 2011-2022 走看看