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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 580解锁bl工具_小米解锁卡刷教程

    580解锁bl工具_小米解锁卡刷教程本期教程教你如何给小米手机解锁卡刷在浏览器输入小米社区官网:xiaomi.cn,点击手机解锁点击立即解锁点击解锁工具下载,下载完成后解压在手机上打开设置-我的设备-全部参数,连续点击MIUI版本7次即可开启开发者模式返回到设置主界面,点击更多设置-开发者选项-设备解锁状态,并关闭WiFi网络,开启数据网络进行绑定解bl会清除所有数据,请自行备份数据备份完数据后,手机关机。按电源键+音量键…

    2022年6月11日
    91
  • vue生成二维码并保存图片_vue实现扫描二维码

    vue生成二维码并保存图片_vue实现扫描二维码一、生成简单的二维码(不带图片)1.引入插件npminstallqrcode–save2.页面中使用<divid=”qrcode”class=”erweima”></div>页面中引入importQRCodefrom”qrcodejs2″;methods:{qrcode(){this.$nextTick(()=>{letqrcode=newQRCode(“qrcode”,{

    2022年10月3日
    1
  • linux系统sdio接口wifi编程,3个SDIO接口WiFi模块/WiFi+蓝牙组合模块介绍-SKYLAB「建议收藏」

    linux系统sdio接口wifi编程,3个SDIO接口WiFi模块/WiFi+蓝牙组合模块介绍-SKYLAB「建议收藏」原标题:3个SDIO接口WiFi模块/WiFi+蓝牙组合模块介绍-SKYLAB听说你在找SDIO接口WiFi模块/WiFi蓝牙组合模块?SKYLAB有推出3款支持SDIO接口的小尺寸WiFi模块和WiFi+蓝牙组合模块。以下是这三款模块详情。(1)支持SDIO接口WiFi模块WG223WG223是一款SDIO接口(兼容SDIO1.1/2.0/3.0)WiFi模块,专门为实现嵌入式系统…

    2022年10月3日
    0
  • java多线程—Java 多线程同步的五种方法

    Java 多线程同步的五种方法

    2022年2月24日
    47
  • idea2021.4.14激活码_通用破解码

    idea2021.4.14激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    63
  • 微信开放平台扫码登录[通俗易懂]

    微信开放平台扫码登录[通俗易懂]微信开放平台扫码登录的功能只有已经认证过的微信公众号才可以使用,很多学习微信的同学可能没办法使用这个功能,但是别担心,以下网址中有很多账号可以使用:【想要获取更多公众账号可以关注微信公众号:小D课堂】https://mp.weixin.qq.com/s?__biz=MzUyMDg1MDE2MA%3D%3D&amp;idx=2&amp;mid=2247483689&amp;sn=5…

    2022年6月14日
    86

发表回复

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

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