v9.10.2019.0101  全面巩固批量Insert/Update/Upsert,支持数据备份、恢复和同步,支持实体列表保存到文件以及加载
大石头 authored at 2019-01-01 13:38:33
4.07 KiB
X
using System.ComponentModel;
using System.Net;
using NewLife.Http;
using Xunit;

namespace XUnitTest.Http;

/// <summary>HTTP 处理器异步契约(IHttpHandler.ProcessRequestAsync)实网测试</summary>
public class HttpAsyncHandlerTests : IDisposable
{
    private readonly HttpServer _server;
    private readonly Uri _baseUri;

    public HttpAsyncHandlerTests()
    {
        var server = new HttpServer { Port = 0 };
        server.Start();

        _server = server;
        _baseUri = new Uri($"http://127.0.0.1:{server.Port}");
    }

    public void Dispose() => _server?.Dispose();

    /// <summary>异步处理器:等待后写响应,记录调用次数</summary>
    private sealed class AsyncHandler : IHttpHandler
    {
        public Int32 Calls;

        public async Task ProcessRequestAsync(IHttpContext context)
        {
            Interlocked.Increment(ref Calls);

            await Task.Delay(10).ConfigureAwait(false);

            context.Response.SetResult("async-ok");
        }
    }

    [Fact]
    [DisplayName("HTTP异步处理器_等待后写响应_响应正常")]
    public async Task AsyncHandler_Awaited()
    {
        var handler = new AsyncHandler();
        _server.Map("/async", handler);

        var client = new HttpClient { BaseAddress = _baseUri };
        var text = await client.GetStringAsync("/async");

        Assert.Equal("async-ok", text);
        Assert.Equal(1, handler.Calls);
    }

    [Fact]
    [DisplayName("HTTP异步委托_返回Task泛型结果_取回响应体")]
    public async Task AsyncDelegate_TaskResult()
    {
        _server.Map("/delegate", new DelegateHandler
        {
            Callback = (Func<IHttpContext, Task<String>>)(async ctx =>
            {
                await Task.Delay(10).ConfigureAwait(false);

                return "delegate-ok";
            })
        });

        var client = new HttpClient { BaseAddress = _baseUri };
        var text = await client.GetStringAsync("/delegate");

        Assert.Equal("delegate-ok", text);
    }

    [Fact]
    [DisplayName("HTTP异步处理器_抛业务异常_按同步口径映射状态码")]
    public async Task AsyncHandler_Throws_MapsStatusCode()
    {
        _server.Map("/boom", new DelegateHandler
        {
            Callback = (HttpProcessAsyncDelegate)(async ctx =>
            {
                await Task.Yield();

                throw new HttpException(HttpStatusCode.BadGateway, "async-fail");
            })
        });

        var client = new HttpClient { BaseAddress = _baseUri };
        var res = await client.GetAsync("/boom");

        Assert.Equal(HttpStatusCode.BadGateway, res.StatusCode);
    }

    [Fact]
    [DisplayName("HTTP异步处理器_经中间件管道_顺序与同步口径一致")]
    public async Task AsyncHandler_ThroughMiddleware()
    {
        var log = new List<String>();
        _server.Use(async (ctx, next) =>
        {
            log.Add("before");

            await next();

            log.Add("after");
        });

        _server.Map("/pipeline", new DelegateHandler
        {
            Callback = (HttpProcessAsyncDelegate)(async ctx =>
            {
                await Task.Delay(5).ConfigureAwait(false);

                log.Add("handler");
                ctx.Response.SetResult("mw-ok");
            })
        });

        var client = new HttpClient { BaseAddress = _baseUri };
        var text = await client.GetStringAsync("/pipeline");

        Assert.Equal("mw-ok", text);
        Assert.Equal(["before", "handler", "after"], log);
    }

    [Fact]
    [DisplayName("HTTP同步处理器_仍走同步入口_行为不变")]
    public async Task SyncHandler_Unchanged()
    {
        var called = 0;
        _server.Map("/sync", new DelegateHandler
        {
            Callback = (HttpProcessDelegate)(ctx =>
            {
                called++;
                ctx.Response.SetResult("sync-ok");
            })
        });

        var client = new HttpClient { BaseAddress = _baseUri };
        var text = await client.GetStringAsync("/sync");

        Assert.Equal("sync-ok", text);
        Assert.Equal(1, called);
    }
}