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

Posted

技术标签:

【中文标题】使用 PerWebRequest 生活方式测试 Castle Windsor 组件【英文标题】:Testing Castle windsor Component with PerWebRequest lifestyle 【发布时间】:2011-08-12 12:02:43 【问题描述】:

我正在尝试对涉及的城堡温莎进行一些测试,在我的一项测试中,我想检查温莎安装程序,因此我检查容器是否可以根据其接口解析我的组件。

到目前为止,一切顺利,当组件在其安装程序中具有 PerWebRequest 生活方式时,问题就开始了,起初它抱怨 HttpContext.Current 为空,解决了在测试设置中创建假 Context 我现在有了这个nunit 测试中的异常

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

下的部分

当我从 NUnit 运行它时,我如何在 Windsor 中注册模块或类以便它工作,或者如何模拟,因为在这个测试中不是真正的 Web 请求,只是检查容器是否解析输入。

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

提前排队

【问题讨论】:

我昨天在***.com/questions/5772497/…问了一个类似的问题 【参考方案1】:

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

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

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

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

container.Kernel.ComponentModelCreated += Kernel_ComponentModelCreated;

void Kernel_ComponentModelCreated(Castle.Core.ComponentModel model)

    if (model.LifestyleType == LifestyleType.Undefined)
        model.LifestyleType = LifestyleType.Transient;

【讨论】:

Mauricio,非常感谢您的回答,我已经为这个挠头了一段时间。温莎有点新。 感谢您的想法。需要按预期对覆盖功能进行单元测试。通过两次解析相同的 IType 并检查对象是否相同,为 LifestyleSingleton 完成此操作。 它有效,但我必须检查生活方式 PerWebRequest 而不是未定义。自从几年前发布您的答案以来,也许这是行为上的变化。因此条件变为:if (model.LifestyleType == Castle.Core.LifestyleType.PerWebRequest)。谢谢!【参考方案2】:

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

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

【讨论】:

【参考方案3】:

如果您使用 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);
    

【讨论】:

【参考方案4】:

我最终实现了这个扩展。 ATTN: 必须调用 before 加载具有 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;

【讨论】:

以上是关于使用 PerWebRequest 生活方式测试 Castle Windsor 组件的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 对 C 代码进行单元测试的最简单方法

为 C 代码编写单元测试

c中包含static函数的lib怎么进行gtest单元测试

使用 XCUI 进行 UI 测试

python接口自动化测试(c测试环境的准备)

无回显不出网命令执行测试方式