Owin.TestServer 测试需要身份验证的中间件

Owin.TestServer To Test a Middleware that Requires Authentication

我有一个中间件方法需要解析 context.Authentication.User.Identity.Name 才能正确执行。但是,在编写单元测试时,这些属性显然是空的,因为没有发生登录。我没有使用 Oauth 或任何与此中间件相关的身份验证(除了明显的名称 属性),因为它应该在另一个中间件的其他地方处理(以提升我正在开发的组件的 re-use/flexibility)。有没有办法 mock/fake 这个值,所以我可以 运行 我的测试?我已经尝试了我能想到的所有方法来伪造登录,但我只是停留在这一点上。需要明确的是,中间件需要的值不是 webapi 调用等。

//Arrange
var resolver = A.Fake<IDependencyResolver>();
A.CallTo(() => resolver.GetService(typeof(ISomeService))).Returns(new TestService());

using (var server = TestServer.Create(app =>
{
    app.UseMyMiddleware(new MyMiddlewareOptions()
    {
        DependencyResolver = resolver
    });

    app.Run(async ctx =>
    {
        await ctx.Response.WriteAsync(ctx.Request.Path.Value);
    });
}))
{
    //Act
    var response = await server.CreateRequest("/").GetAsync();

    //Assert
    A.CallTo(() => resolver.GetService(typeof(ISomeService)))
                           .MustHaveHappened(Repeated.Exactly.Once);
    Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
    //Etc.
}

所以这里有一种方法,我认为它并不令人兴奋,但它确实起作用了。我会等待接受,因为我认为应该有更好的方法。

public class TestFakeLoginMiddleware : OwinMiddleware
{
    public TestFakeLoginMiddleware(OwinMiddleware next) : base(next)
    {
    }

    public override async Task Invoke(IOwinContext context)
    {
        var identity = A.Fake<IIdentity>();
        A.CallTo(() => identity.Name).Returns("TEST@domain.local");
        var user = new ClaimsPrincipal(identity);
        context.Request.Context.Authentication.User = user;
        await Next.Invoke(context);
    }
}

有点晚了,我知道,但是你能不能只创建一个新的 ClaimsIdentity?

public override async Task Invoke(IOwinContext context)
{
    var identity= new ClaimsIdentity(new List<Claim> {
        new Claim(ClaimTypes.Name, "TEST@domain.local")
    });
    var user = new ClaimsPrincipal(identity);
    context.Request.Context.Authentication.User = user;
    await Next.Invoke(context);
}