使用PerWebRequest生活方式测试Castle windsor组件

时间:2011-04-25 18:20:57

标签: testing components castle-windsor castle perwebrequest

我正在尝试对涉及的城堡windsor进行一些测试,在我的一个测试中,我想检查windsor安装程序,所以我检查容器是否可以解析我的组件给定其界面。

到目前为止,非常好,问题在组件在其安装程序中具有PerWebRequest生活方式时开始,首先它抱怨HttpContext.Current为null,有一个解决了在测试设置中创建假上下文我现在有这个nunit测试中的例外

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

下的部分

当我从NUnit运行时,如何在windsor中注册模块或类,以便它可以工作,或者如何模拟,因为在此测试中并不是真正的Web请求,只需检查容器是否解决了类型。

如果我在真正的webrequest之外对这个组件进行任何集成测试,也会发生同样的事情,有没有办法使这个工作或真的模拟一个Web请求,以便可以运行这些测试?

提前交易

费尔

4 个答案:

答案 0 :(得分:17)

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

如果您正在编写具有单个请求范围的集成测试,则单例应该这样做。

如果您正在编写跨越多个请求的集成测试,则可以使用contextual lifestyle来模拟请求的范围。

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

container.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;

...

void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
    if (model.LifestyleType == LifestyleType.Undefined)
        model.LifestyleType = LifestyleType.Transient;
}

答案 1 :(得分:0)

如果您还想检查范围类型是否是针对每个Web请求的,您也可以这样做

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

答案 2 :(得分:0)

从Windsor的第5版开始,如果您使用的是Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor,那么可接受的答案将不起作用,因为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);
    }
}

答案 3 :(得分:0)

我最终实现了此扩展。 ATTN :必须在加载具有 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);
    }
}

需要这些导入:

using System;
using System.Collections.Generic;
using Castle.Core;
using Castle.Facilities.AspNet.SystemWeb;
using Castle.Windsor;