Ask a questionAsk a question
 

AnswerAssembly Not Found Serialization Exception

  • Tuesday, December 18, 2007 7:14 PMMike Livenspargar Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I have a unit test project in which all tests fail due to a SerializationException thrown when the ClassInitialize method in a test class attempts to execute. The exception message is ‘Unable to find assembly …’ where the assembly specification is for a dll from another project in the solution.

    I have several other solutions that are very similar and the unit tests from those solutions run fine. I’ve run the tests using VS2008 MSTest from the command line and compared the fusion logs from a successful run and the failing project. There are differences as follows:

    Successful

    DisplayName: fully specified

    Initial Private Path: PublicAssemblies;PrivateAssemblies

    Context: LoadFrom load context

     

    Failed

    DisplayName: partial

    Initial Private Path: NULL

    Context:  default load context

     

    The solutions are all VS2005 solutions converted to VS2008. At this point I’ve actually deleted the original test project from the failing solution and added a new one, but the new test project has the same problem.

     

    What is causing this failure to find a referenced assembly when running unit tests, and how can I correct the problem? What other information will help diagnose the problem?

     

    Thank you,

    Mike

     

Answers

  • Thursday, January 10, 2008 1:30 AMNeal Fowler - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

     

    Mike,

     

    Thank you for your detailed repro steps.  We have recently become aware of this issue; it has been reported to us by a number of different customers now.  We understand what is causing this problem, and have every intention of fixing it, but cannot yet commit to a timeframe for doing so.

     

    Here is a brief explanation of the problem.  Each test method executes in its own AppDomain.  This domain is able to resolve assemblies in the deployment "Out" directory, which holds test assemblies, assemblies under test, and anything explicitly deployed by the test code.  When a test method completes, the executing thread returns to the default domain for the VSTestHost process, which unfortunately now (in VS2008) is ignorant of the "Out" directory.  In this transition back to the default domain, the .NET remoting infrastructure attempts to deserialize the object set on Thread.CurrentPrincipal, but can't resolve the assembly that houses its type - hence the exception.  The same would apply to any objects set, for example, on System.Runtime.Remoting.Messaging.CallContext.

     

    Unfortunately, I do not have a good, general workaround to recommend.  You could try something ugly like altering the probing path for VSTestHost.exe to include the path to your assembly under test, but of course that only works if you are an admin on the box.

     

    Regards,

     

    Neal Fowler

    VSTS Team Test

     

All Replies

  • Wednesday, December 19, 2007 12:27 AMDavid R. Williamson MSFTMSFTUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi Mike,

     

    Are the other assemblies copied to the deployment directory?

     

    Can you describe the situation a bit more of these different assemblies, the relationships between them, and how they reference each other?

     

    Cheers,

    David

     

  • Wednesday, December 19, 2007 10:30 PMMike Livenspargar Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi David:

     

    The problem solution contains the following projects:

     ProjectA

    ProjectB

    ProjectC

    ProjectTest

     

    Code in ProjectTest only references ProjectC, and ProjectC references ProjectA and ProjectB. ProjectB does not reference ProjectA, nor vice versa. The references are project references within the solution.  I’ve checked the TestResults\*\Out directory after a failed test run and the directory does contain these four projects. All of the assemblies are strongly-named. I checked the references with ILDasm and confirmed that the referenced version numbers match the assembly version numbers.

    Other solutions containing Projects A, B, C, etc and their own ProjectTest run tests without issue.

    ProjectTest contains two [TestClass] classes. One of the classes has an [AssemblyInitialize] method and the other class has a single [TestMethod] with a simple Assert.IsTrue(true) test. When the AssemblyIntialize method is empty and the TestMethod class does not contain a [ClassInitialize] method then the test passes.

    If from within the AssemblyInitialize method I call a static method on a class in ProjectC and include an empty ClassInitialize method in the TestMethod class then the test fails with a “SerializationException, ProjectC not found” error.  If I then comment out just the ClassInitialize method the test will pass.

    Other solutions in which the tests run successfully contain the static method call/ClassInitialize pattern.

    I know this is hard to diagnose by description. Please let me know if there’s any further information I can provide.

    Thanks,

    Mike

     

  • Friday, January 04, 2008 6:50 PMMike Livenspargar Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I’m still dead in the water with this issue. Here are some code samples showing what works and what doesn’t work.

    This code throws an exception ‘SerializationException: Unable to find assembly ProjectC…’ when I try to execute the test.

    Code Block

        [TestClass]

        public class AssemblyInitialization

        {

            [AssemblyInitialize]

            public static void InitializeAssembly(TestContext testContext)

            {

                ProjectCClass1.Application.ConnectionString = "value";

                ProjectCClass2.Initialize(new List<string>());

            }

        }

     

        [TestClass]

        public class UnitTest1

        {

            [ClassInitialize]

            public static void InitializeClass(TestContext @__testContext)

            {

            }

     

            [TestMethod]

            public void TestMethod1()

            {

                Assert.IsTrue(true);

            }

        }

     

     

     

    If I comment out the ClassInitialize method in the UnitTest1 class the test passes:

    Code Block

        [TestClass]

        public class AssemblyInitialization

        {

            [AssemblyInitialize]

            public static void InitializeAssembly(TestContext testContext)

            {

                ProjectCClass1.Application.ConnectionString = "value";

                ProjectCClass2.Initialize(new List<string>());

            }

        }

     

        [TestClass]

        public class UnitTest1

        {

            //[ClassInitialize]

            //public static void InitializeClass(TestContext @__testContext)

            //{

            //}

     

            [TestMethod]

            public void TestMethod1()

            {

                Assert.IsTrue(true);

            }

        }

     

     

     

    If I comment out the call to ProjectCClass2.Initialize in the AssemblyInitialize method the test passes:

    Code Block

        [TestClass]

        public class AssemblyInitialization

        {

            [AssemblyInitialize]

            public static void InitializeAssembly(TestContext testContext)

            {

                ProjectCClass1.Application.ConnectionString = "value";

                //ProjectCClass2.Initialize(new List());

            }

        }

     

        [TestClass]

        public class UnitTest1

        {

            [ClassInitialize]

            public static void InitializeClass(TestContext @__testContext)

            {

            }

     

            [TestMethod]

            public void TestMethod1()

            {

                Assert.IsTrue(true);

            }

        }

     

     

     

    I can include the call to ProjectCClass2.Initialize in TestMethod1 and the test passes:

    Code Block

        [TestClass]

        public class AssemblyInitialization

        {

            [AssemblyInitialize]

            public static void InitializeAssembly(TestContext testContext)

            {

                ProjectCClass1.Application.ConnectionString = "value";

                //ProjectCClass2.Initialize(new List());

            }

        }

     

        [TestClass]

        public class UnitTest1

        {

            [ClassInitialize]

            public static void InitializeClass(TestContext @__testContext)

            {

            }

     

            [TestMethod]

            public void TestMethod1()

            {

                ProjectCClass2.Initialize(new List<string>());

                Assert.IsTrue(true);

            }

        }

     

     

     

    Can anybody give me a clue that will help me resolve this issue?

    Thank you,

    Mike

     

  • Tuesday, January 08, 2008 7:03 PMMike Livenspargar Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Here is how to duplicate the problem:

    1.       Using VS2008 create a new solution with a class library project.

    2.       Replace the code in Class1.cs with the following

     

    Code Block

    using System;

    using System.Collections.Generic;

    using System.Security.Principal;

    using System.Threading;

     

    namespace ProjectA

    {

        [Serializable]

        public class MyIdentity : IIdentity

        {

            public string AuthenticationType

            {

                get { return String.Empty; }

            }

     

            public bool IsAuthenticated

            {

                get { return false; }

            }

     

            public string Name

            {

                get { return String.Empty; }

            }

        }

     

        [Serializable]

        public class MyPrincipal : IPrincipal

        {

            private static MyIdentity _identity;

            private MyPrincipal()

            {

            }

     

            public static void Initialize()

            {

                _identity = new MyIdentity();

                MyPrincipal principal = new MyPrincipal();

                Thread.CurrentPrincipal = principal; // comment out this line and test will pass

            }

     

            public IIdentity Identity

            {

                get { return _identity; }

            }

     

            public bool IsInRole(string role)

            {

                return false;

            }

        }

    }

     

     

     

    3.       Add a new Test project to the solution.

    4.       Add a reference to the class library created in step 1 to the test project (in my code that class library is ProjectA).

    5.       Replace the code in UnitTest1.cs with the following

    Code Block

    using System;

    using System.Collections.Generic;

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using ProjectA;

     

    namespace TestProject

    {

        [TestClass]

        public class AssemblyInitialization

        {

            [AssemblyInitialize]

            public static void InitializeAssembly(TestContext testContext)

            {

                MyPrincipal.Initialize();

            }

        }

     

        [TestClass]

        public class UnitTest1

        {

            [ClassInitialize]

            public static void InitializeClass(TestContext testContext)

            {

            }

     

            [TestMethod]

            public void TestMethod1()

            {

                Assert.IsTrue(true);

            }

        }

    }

     

     

     

    6.       Build the solution and run the test. In my environment this fails with a SerializationException ‘Unable to find ProjectA…’.

    7.       Comment out the’ Thread.CurrentPrincipal = principal;’ line in the Initialize method of MyPrincipal in the class library. Build the solution and run the test. In my environment the test now passes.

    The actual test and class library projects we use were converted from their VS2005 versions, where they ran fine. This is new behavior in the VS2008 product.

    What can I do?

    Thanks,

    Mike

     

  • Thursday, January 10, 2008 1:30 AMNeal Fowler - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

     

    Mike,

     

    Thank you for your detailed repro steps.  We have recently become aware of this issue; it has been reported to us by a number of different customers now.  We understand what is causing this problem, and have every intention of fixing it, but cannot yet commit to a timeframe for doing so.

     

    Here is a brief explanation of the problem.  Each test method executes in its own AppDomain.  This domain is able to resolve assemblies in the deployment "Out" directory, which holds test assemblies, assemblies under test, and anything explicitly deployed by the test code.  When a test method completes, the executing thread returns to the default domain for the VSTestHost process, which unfortunately now (in VS2008) is ignorant of the "Out" directory.  In this transition back to the default domain, the .NET remoting infrastructure attempts to deserialize the object set on Thread.CurrentPrincipal, but can't resolve the assembly that houses its type - hence the exception.  The same would apply to any objects set, for example, on System.Runtime.Remoting.Messaging.CallContext.

     

    Unfortunately, I do not have a good, general workaround to recommend.  You could try something ugly like altering the probing path for VSTestHost.exe to include the path to your assembly under test, but of course that only works if you are an admin on the box.

     

    Regards,

     

    Neal Fowler

    VSTS Team Test

     

  • Tuesday, March 04, 2008 2:01 AMbrjo100 Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Neal -

    Could this be the same bug that is causing this:
    http://forums.microsoft.com/Forums/ShowPost.aspx?PostID=2917919&SiteID=1

    Or:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2789748&SiteID=1

    Thanks
  • Thursday, March 06, 2008 10:22 PMskt Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Neal,

    We too are experiencing this same problem.   I was fooling around with it and noticed that if i manually copied the assembly under test to the AppDomain.CurrentDomain.BaseDirectory, this exception does not happen anymore.

    However if you look at the bindings when the tests run, the assembly under test is being loaded by VSTestHost from the 'out'  deployment directory

    So putting a copy of the assembly under test in APPBASE seems to suppress this exception when the executing thread returns to the default domain.   Is that even a safe workaround?


  • Monday, November 09, 2009 9:02 PMSimon Francesco Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Hi Neal,
    This still appears to be an issue in Visual Studio 2010 Beta 2.

    In my case it was Data in the CallContext that caused the issue.

    I made a call to CallContext.FreeNamedDataSlot("mycalldata") as the last line in my test and it did not throw an exception.

    Any update as to progress in this area?

    AS an aside:
    Would it be possible that VSTestHost.exe and the  WebDev Http Server share the same bug, I get a very similar exception when using cassini to debug code. Details reported in this Connect issue.
    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=274696&wa=wsignin1.0
    and also referenced in many other places:
    http://stackoverflow.com/questions/1107201/cassini-exception-unhandeld
    http://www.leandrodg.com.ar/blog/2007/12/cassini-serializationexception-type-is-not-resolved-for-member/

    Cheers
    Simon