繁体   English   中英

在 ASP.NET WebApi 2 中测试 OWIN 中间件:如何设置 cookie?

[英]Testing OWIN Middleware in ASP.NET WebApi 2: How to set cookies?

我正在尝试在 ASP.NET WebApi 2 应用程序中测试 OWIN 中间件组件。 中间件应该查看传入请求的 cookie,在将请求传递给下一个组件之前修改请求中的一些内容,并可能在出路时设置一个 cookie。

什么是绊倒我的是, OwinRequest.Cookies属性的类型的RequestCookieCollection ,这似乎并没有允许修改,而本身的属性只读这意味着我不能使用RequestCookieCollection(IDictionary<string,string>)构造函数来初始化一个已经包含 cookie 的集合,并在请求中设置它。

我想做这样的事情:

var context = new OwinContext();
// option 1:
context.Request.Cookies.Append("cookie-name", "cookie-value");
// option 2:
var cookies = new RequestCookieCollection(new Dictionary<string, string>{ { "cookie-name", "cookie-value" } });
context.Request.Cookies = cookies;

await myMiddleware.Invoke(context);

// Assert stuff about context.Response

但由于上述原因,这不起作用。

我曾希望不必完全模拟IOwinContext ,因为使用功能良好的RequestResponse对象设置它非常方便(除其他外,我需要在我的实现中查看Request.User.Identity.IsAuthenticated ) .

使用以下作为单元测试示例中间件的主题

using RequestDelegate = Func<IOwinContext, Task>;

class MyMiddleware {
    private readonly RequestDelegate next;

    public MyMiddleware(RequestDelegate next) {
        this.next = next;
    }

    public async Task Invoke(IOwinContext context) {
        //The middleware is supposed to look at the cookies of the incoming request, 
        var request = context.Request;
        var authenticated = request.User.Identity.IsAuthenticated;

        var cookies = request.Cookies;
        if (cookies["cookie-name"] != null) {
            // 1. check for existence of a cookie on the incoming request. 
            //if the cookie exists, use its value to set a header, 
            //so that the pipline after this component thinks the header was always present.
            request.Headers.Append("header-name", "header-value");
        }

        //2. call the next component.
        await next.Invoke(context);

        //3. on the way out, check for some conditions, and possibly set a cookie value.
        if (authenticated) {
            context.Response.Cookies.Append("cookie-name", "cookie-value");
        }
    }
}

并使用提供的有关所需行为的详细信息,

很难使用完整OwinContext所需的所有管道对控制器进行单元测试。

您已经说明了许多有关访问某些成员的限制。

然而,Owin 提供了许多抽象,允许对孤立的单元测试进行模拟/存根/伪造所需的行为。

以下示例基于上面提供的主题,并使用Moq模拟框架和具体实现来正确设置和执行主题中间件的隔离单元测试。

[TestClass]
public class OwinMiddlewareCookiesTest {
    [Test]
    public async Task MyMiddleware_Should_Set_RequestHeader_And_ResponseHeader() {
        //Arrange
        var cookieStore = new Dictionary<string, string> { { "cookie-name", "cookie-value" } };
        var cookies = new RequestCookieCollection(cookieStore);

        var request = Mock.Of<IOwinRequest>();
        var requestMock = Mock.Get(request);
        requestMock.Setup(_ => _.Cookies).Returns(cookies);
        requestMock.Setup(_ => _.User.Identity.IsAuthenticated).Returns(true);
        requestMock.Setup(_ => _.Headers.Append(It.IsAny<string>(), It.IsAny<string>()));

        var response = new OwinResponse();

        var context = Mock.Of<OwinContext>();
        var contextMock = Mock.Get(context);
        contextMock.CallBase = true;
        contextMock.Setup(_ => _.Request).Returns(request);
        contextMock.Setup(_ => _.Response).Returns(response);

        RequestDelegate next = _ => Task.FromResult((object)null);

        var myMiddleware = new MyMiddleware(next);

        //Act
        await myMiddleware.Invoke(context);

        //Assert
        requestMock.Verify(_ => _.Headers.Append("header-name", "header-value"));
        response.Headers.ContainsKey("Set-Cookie");
    }
}

只需要模拟必要的依赖项,测试就可以完成并验证预期的行为。

由于无法覆盖请求实现的Cookies属性,因此必须使用抽象。 然而,这在模拟所需行为方面提供了更大的灵活性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM