是否可以在VS 2010的单元测试中使用逻辑调用上下文? [英] Is it possible to use the logical call context within a unit test in VS 2010?

查看:82
本文介绍了是否可以在VS 2010的单元测试中使用逻辑调用上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使此测试不引发异常?看来,将任何非GACed类添加到逻辑调用上下文中都会导致在测试的第2行中引发异常.

Is it possible to make this test not throw an exception? It appears that adding any non-GACed class into the logical call context causes an exception to be thrown in line 2 of the test.

测试 'TestProject1.UnitTest1.TestMethod1' 失败:测试方法 TestProject1.UnitTest1.TestMethod1 抛出异常: System.Configuration.ConfigurationErrorsException: 加载时发生错误 配置文件:类型不是 为成员解决 'TestProject1.Bar,TestProject1, 版本= 1.0.0.0,文化=中性, PublicKeyToken = null". ---> System.Runtime.Serialization.SerializationException: 会员的类型无法解析 'TestProject1.Bar,TestProject1, 版本= 1.0.0.0,文化=中性, PublicKeyToken = null'.

Test 'TestProject1.UnitTest1.TestMethod1' failed: Test method TestProject1.UnitTest1.TestMethod1 threw exception: System.Configuration.ConfigurationErrorsException: An error occurred loading a configuration file: Type is not resolved for member 'TestProject1.Bar,TestProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. ---> System.Runtime.Serialization.SerializationException: Type is not resolved for member 'TestProject1.Bar,TestProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

namespace TestProject1 {
    [ Serializable]
    public class Bar {

    }

    [TestClass]
    public class UnitTest1 {
        [TestMethod]
        public void TestMethod1() {
            CallContext.LogicalSetData("foo", new Bar());
            ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None );
        }
    }
}

为什么?!?!?

推荐答案

基本上,这是设计用于在测试运行期间承载测试代码的流程的问题.测试在与测试主机进程的默认AppDomain不同的AppDomain中运行.从一个AppDomain到另一个AppDomain进行调用时,需要将调用上下文反序列化到目标AppDomain中.在您的情况下,ConfigurationManager.OpenExeConfiguration最终会调用AppDomain.get_Evidence.这样会导致从托管测试的AppDomain到默认AppDomain的调用.

Basically, this is a problem with the design of the process used to host the test code during a test run. Tests are run in a separate AppDomain from the test host process' default AppDomain. When a call is made from one AppDomain to another, the call context needs to be deserialized into the target AppDomain. In your case, ConfigurationManager.OpenExeConfiguration ends up calling AppDomain.get_Evidence. This results in a call from the AppDomain hosting the tests to the default AppDomain.

默认的AppDomain的基本目录是测试主机可执行文件的安装目录.默认情况下,这是%ProgramFiles%\ Microsoft Visual Studio 10.0 \ Common7 \ IDE" .托管测试的AppDomain使用测试运行部署位置的基本目录.默认情况下,这是< solutiondir> \ TestResults \< testrun> \ Out" .因此,用于运行测试的AppDomain可以解析序列化的类型,因为它们的程序集位于Out目录中(尽管它们已经被加载到测试的AppDomain中,因为此代码已执行),而默认的AppDomain无法.

The default AppDomain's base directory is where the test host executable was installed to. By default, this is "%ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE". The AppDomain hosting the tests uses a base directory of the test run deployment location. By default, this is "<solutiondir>\TestResults\<testrun>\Out". Thus, the AppDomain used to run the tests can resolve the serialized types as their assemblies lie in the Out directory (regardless, they're already loaded into the test's AppDomain because this code executes) while the default AppDomain cannot.

GAC可以对包含序列化类型的程序集进行工作,因为在程序集解析期间会检测到GAC.这是一种可能的解决方案.但是,您需要在每次测试运行时将它们安装到GAC上,这需要强大的名称和管理特权.

GACing the assemblies containing the serialized types works because the GAC is probed during assembly resolution. This is one possible solution. However, you would need to install them to the GAC on every test run and this requires strong names and administrative privileges.

另一种可能的解决方案是将程序集复制到默认AppDomain的探测路径.这将是上面列出的基本目录,并且是QTAgent.exe.config或QTAgent32.exe.config中列出的privatePaths(运行的路径取决于您是否使用64位操作系统以及托管平台中的托管平台设置).测试设置).与所有专用探测路径一样,这些目录必须是基本目录的子目录.您可以创建一个具有适当访问权限的新子目录,将该目录名称添加到.exe.config文件中的privatePaths中,然后在测试安装过程中将包含序列化类型的程序集复制到该目录中.只要您将程序集复制到的目录允许您写入,该解决方案就不需要管理特权或强命名功能.

Another possible solution would be to copy the assemblies to the probing path of the default AppDomain. This would be the base directory listed above and the privatePaths listed in QTAgent.exe.config or QTAgent32.exe.config (which one runs depends on whether or not you're using a 64-bit operating system and the hosting platform setting in the test settings). As with all private probing paths, these directories must be sub-directories of the base directory. You could create a new sub-directory with the appropriate access permissions, add the directory name to the privatePaths in the .exe.config files, and then copy the assemblies containing the serialized types into this directory during test setup. This solution would not require administrative privileges or strong naming, provided the directory you're copying the assemblies to allows you to write to it.

不幸的是,这些解决方案都不是理想的,因为如果在每次测试运行之前未正确更新程序集,它们都可能在测试的AppDomain和默认的AppDomain中运行的代码之间引入类型不匹配的可能性. Microsoft将需要适当的修复程序(例如,当默认的AppDomain需要解析类型时,让测试主机进程自动探测测试部署目录).我没有使用测试工具,因此我无法评论考虑到实施细节的真正修复所需要的内容.

Unfortunately, neither of these solutions are ideal as they can introduce the possibility for type mismatch between the code running in the tests' AppDomain and the default AppDomain if the assemblies are not updated properly before each test run. A proper fix would be required from Microsoft (say having the test host process automatically probe the test deployment directory when the default AppDomain needs to resolve types). I didn't work on the test tools, so I can't comment on what a real fix, taking implementation details into consideration, would require.

编辑:如果您选择了这些解决方案"之一,则还需要禁止测试主机进程在两次测试运行之间保持活动状态.这是因为默认的AppDomain将继续存在,并且包含序列化类型的程序集将保持加载状态,从而防止您在下一次测试运行时对其进行更新.控制此选项的方法是工具->选项->测试工具->测试执行"下的让测试执行引擎在测试运行之间保持运行".

Edit: if you do elect one of these "solutions", you will also need to disable the test host process from staying alive between test runs. This is because the default AppDomain will stick around and the assemblies containing the serialized types will remain loaded, preventing you from updating them on the next test run. The option to control this is "Keep test execution engine running between test runs" under "Tools -> Options -> Test Tools -> Test Execution".

这篇关于是否可以在VS 2010的单元测试中使用逻辑调用上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆