Testing 使用PerWebRequest lifestyle测试Castle windsor组件

Testing 使用PerWebRequest lifestyle测试Castle windsor组件,testing,components,castle-windsor,castle,perwebrequest,Testing,Components,Castle Windsor,Castle,Perwebrequest,我正在尝试对castle windsor进行一些测试,在我的一个测试中,我想检查windsor安装程序,因此我检查容器是否可以解析给定接口的组件 到目前为止,很好,当组件在其安装程序中具有PerWebRequest生活方式时,问题就开始了,起初它抱怨HttpContext.Current为null,解决了在测试设置中创建假上下文的问题,现在nunit测试中出现了此异常 System.Exception:看起来您忘记注册http模块Castle.MicroKernel.Lifestyle.PerW

我正在尝试对castle windsor进行一些测试,在我的一个测试中,我想检查windsor安装程序,因此我检查容器是否可以解析给定接口的组件

到目前为止,很好,当组件在其安装程序中具有PerWebRequest生活方式时,问题就开始了,起初它抱怨HttpContext.Current为null,解决了在测试设置中创建假上下文的问题,现在nunit测试中出现了此异常

System.Exception:看起来您忘记注册http模块Castle.MicroKernel.Lifestyle.PerWebRequestLifestyle模块了 将“”添加到web.config上的节中。如果您在集成模式下运行IIS7,则需要将其添加到下的部分

当我从NUnit运行此测试时,我如何在windsor中注册模块或类以使其工作,或者如何进行模拟,因为在本测试中,这不是真正的web请求,只是检查容器是否解析了类型

如果我在一个真正的webrequest之外使用这个组件进行任何集成测试,也会发生同样的事情,有什么方法可以让它工作或者真正模拟一个web请求,这样就可以运行这个测试了吗

先发制人


Fer

在测试中,您可以订阅ComponentModelCreated事件,并将每个web请求组件的生活方式更改为其他方式。().

如果您正在使用单个请求的范围编写集成测试,singleton应该这样做

如果您正在编写一个跨多个请求的集成测试,那么可以使用来模拟请求的范围

编辑:包括示例中的代码(不再可用):


如果您还想检查作用域的类型是否为每个web请求,您也可以这样做

var isPerWebRequestScope = JsonConvert.SerializeObject(model.ExtendedProperties).Contains("Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor")

如果您使用的是
Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor
,则从Windsor版本5开始,接受的答案不起作用,因为PerWebRequest生活方式已经是一种范围化的生活方式

我通过将
ComponentModelCreated
委托更改为以下内容来实现此功能:

void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
    const string CastleScopeAccessorType = "castle.scope-accessor-type";

    if (model.ExtendedProperties.Contains(CastleScopeAccessorType))
    {
        model.ExtendedProperties.Remove(CastleScopeAccessorType);
    }
}

我最终实现了这个扩展收件人:在使用PerWebRequest加载组件之前必须调用

public static class WindsorContainerExtensions
{
    public static IWindsorContainer OverridePerWebRequestLifestyle(this IWindsorContainer container)
    {
        container.Kernel.ComponentModelCreated += model =>
        {
            if (model.IsPerWebRequestLifestyle())
            {
                model.LifestyleType = LifestyleType.Transient;
            }
        };

        return container;
    }

    private static bool IsPerWebRequestLifestyle(this ComponentModel model)
    {
        return model.LifestyleType == LifestyleType.Scoped
            && model.HasAccessorType(typeof(WebRequestScopeAccessor));
    }

    private static bool HasAccessorType(this ComponentModel model, Type type)
        => model.HasExtendedProperty("castle.scope-accessor-type", type);

    private static bool HasExtendedProperty<T>(this ComponentModel model, object key, T expected)
    {
        return model.ExtendedProperties[key] is T actual
            && EqualityComparer<T>.Default.Equals(actual, expected);
    }
}

我昨天在毛里西奥问了一个类似的问题,非常感谢你的回答,这个问题让我挠头已经有一段时间了。温莎有点新。谢谢你的主意。需要按预期对覆盖功能进行单元测试。通过两次解析相同的IType并检查对象是否相同,对lifestyle Singleton实现了这一点。这是可行的,但我必须检查lifestyle PerWebRequest,而不是未定义的。也许这是因为你的答案在几年前发布后行为上的改变。因此条件变为:if(model.LifestyleType==Castle.Core.LifestyleType.PerWebRequest)。非常感谢。
void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
    const string CastleScopeAccessorType = "castle.scope-accessor-type";

    if (model.ExtendedProperties.Contains(CastleScopeAccessorType))
    {
        model.ExtendedProperties.Remove(CastleScopeAccessorType);
    }
}
public static class WindsorContainerExtensions
{
    public static IWindsorContainer OverridePerWebRequestLifestyle(this IWindsorContainer container)
    {
        container.Kernel.ComponentModelCreated += model =>
        {
            if (model.IsPerWebRequestLifestyle())
            {
                model.LifestyleType = LifestyleType.Transient;
            }
        };

        return container;
    }

    private static bool IsPerWebRequestLifestyle(this ComponentModel model)
    {
        return model.LifestyleType == LifestyleType.Scoped
            && model.HasAccessorType(typeof(WebRequestScopeAccessor));
    }

    private static bool HasAccessorType(this ComponentModel model, Type type)
        => model.HasExtendedProperty("castle.scope-accessor-type", type);

    private static bool HasExtendedProperty<T>(this ComponentModel model, object key, T expected)
    {
        return model.ExtendedProperties[key] is T actual
            && EqualityComparer<T>.Default.Equals(actual, expected);
    }
}
using System;
using System.Collections.Generic;
using Castle.Core;
using Castle.Facilities.AspNet.SystemWeb;
using Castle.Windsor;