19

I'm trying to do some testing with castle windsor involved, in one of my tests I want to check the windsor installers, so I check that the container can resolve my components given its interface.

So far, so good, the problem starts when the component has PerWebRequest lifestyle in its installer, at first it complained about HttpContext.Current is null, having that one solved creating a fake Context in test setup I'm now having this exception in nunit test

System.Exception : Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule Add '' to the section on your web.config. If you're running IIS7 in Integrated Mode you will need to add it to section under

As I'm running this from NUnit, how I can register the module or class in windsor so it works, or how can be mocked, as in this test is not really a web request, just checking that the container resolve the type.

And also this same thing will happen if I make any integration tests with this component outside a real webrequest, is there any way to make this work or really mock a web request so this tests can be run?

Tranks in advance

Fer

4

4 回答 4

21

在您的测试中,您可以订阅 ComponentModelCreated 事件并将您的 per-web-request 组件的生活方式更改为其他内容。(示例)。

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

如果您正在编写跨越多个请求的集成测试,您可以使用上下文生活方式来模拟请求的范围。

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

container.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;

…</p>

void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)
{
    if (model.LifestyleType == LifestyleType.Undefined)
        model.LifestyleType = LifestyleType.Transient;
}
于 2011-04-25T19:19:10.617 回答
1

我最终实现了这个扩展。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;
于 2020-04-23T19:37:05.103 回答
1

从 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);
    }
}
于 2019-06-19T06:51:05.317 回答
0

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

var isPerWebRequestScope = JsonConvert.SerializeObject(model.ExtendedProperties).Contains("Castle.Facilities.AspNet.SystemWeb.WebRequestScopeAccessor")
于 2019-06-12T11:51:42.393 回答