是否可以在VS 2010中的单元测试中使用逻辑调用上下文?

aqu*_*nas 16 unit-testing mstest visual-studio-2010

是否有可能使此测试不会抛出异常?似乎将任何非GACed类添加到逻辑调用上下文中会导致在测试的第2行中抛出异常.

测试'TestProject1.UnitTest1.TestMethod1'失败:测试方法TestProject1.UnitTest1.TestMethod1引发异常:System.Configuration.ConfigurationErrorsException:加载配置文件时出错:成员'TestProject1.Bar,TestProject1,Version = 1.0的类型未解析.0.0,Culture = neutral,PublicKeyToken = null'.---> System.Runtime.Serialization.SerializationException:成员'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 );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么?!?!?

Pet*_*ene 27

基本上,这是用于在测试运行期间托管测试代码的过程的设计的问题.测试在测试主机进程的默认AppDomain的单独AppDomain中运行.当从一个AppDomain到另一个AppDomain进行调用时,需要将调用上下文反序列化为目标AppDomain.在你的情况下,ConfigurationManager.OpenExeConfiguration最终打电话AppDomain.get_Evidence.这会导致从托管测试的AppDomain调用默认的AppDomain.

默认AppDomain的基目录是安装测试主机可执行文件的位置.默认情况下,这是"%ProgramFiles%\ Microsoft Visual Studio 10.0\Common7\IDE".托管测试的AppDomain使用测试运行部署位置的基本目录.默认情况下,这是"<solutiondir>\TestResults\<testrun>\Out".因此,在AppDomain用于运行测试可以解决序列化的类型,其组件趴在输出目录(不考虑,他们已经加载到测试的AppDomain中,因为此代码执行),而默认的AppDomain不能.

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

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

遗憾的是,这些解决方案都不是理想的,因为如果在每次测试运行之前未正确更新程序集,它们可能会导致测试AppDomain中运行的代码与默认AppDomain之间的类型不匹配.Microsoft需要进行适当的修复(例如,当默认AppDomain需要解析类型时,让测试主机进程自动探测测试部署目录).我没有使用测试工具,所以我不能评论什么是真正的修复,考虑实现细节,需要.

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


Cod*_*ing 12

Bar实现MarshalByRefObject可以解决这个问题.这允许在测试运行器内部运行的AppDomain中引用类.

[ Serializable]
public class Bar : MarshalByRefObject {

}
Run Code Online (Sandbox Code Playgroud)

  • NUnit运行开始失败的测试时出现了此问题。该解决方案在这种情况下有所帮助。有问题的对象存储在CallContext.LogicalSetData()中。 (2认同)

jua*_*ana 9

当使用逻辑CallContext存储对象时,实现适当的终结逻辑(IDisposable)来清理存储在CallContext中的对象(例如:CallContext.FreeNamedDataSlot)

希望这可以帮助,

Juanjo