Is it possible to use the logical call context within a unit test in VS 2010?

后端 未结 4 525
予麋鹿
予麋鹿 2020-12-30 03:32

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

相关标签:
4条回答
  • 2020-12-30 04:24

    When using logical CallContext to store objects implement the appropriate finalization logic (IDisposable) to clean up objects stored in the CallContext (e.g.: CallContext.FreeNamedDataSlot)

    Hope this helps,

    Juanjo

    0 讨论(0)
  • 2020-12-30 04:25

    Another workaround -that worked for me- could be to initialize the configuration system before any object is added to the logical call context.

    In my case, WCF and WebAPI services were self-hosted within the test environment to have high control of their behaviors (e.g. replace components within IoC container), but had this serialization exception when execution reached authentication via Active Directory. With the help of reflection tool (e.g. IL Spy), I could identify the configuration section (system.directoryservices) AD was trying to read and triggering cross domain serialization issue.

    Placing the following code before starting self-hosted services, solved the problem:

    System.Configuration.ConfigurationManager.GetSection("system.directoryservices");
    

    You can read more explanation here and here

    0 讨论(0)
  • 2020-12-30 04:27

    This problem can be solved by having Bar implement MarshalByRefObject. This allows the class to be referenced in the AppDomain that the test runner is running inside.

    [ Serializable]
    public class Bar : MarshalByRefObject {
    
    }
    
    0 讨论(0)
  • 2020-12-30 04:28

    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.

    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.

    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.

    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.

    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.

    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".

    0 讨论(0)
提交回复
热议问题