chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
hi

supposing i have the following class:
    public class LegacyClass
    {
        private IDisposable _disposable = new MemoryStream();

        ~LegacyClass()
        {
            _disposable.Dispose();
        }
    }


I want to fake it:
        [TestMethod]
        [Isolated]
        public void TestMethod1()
        {
            LegacyClass fake = Isolate.Fake.Instance<LegacyClass>();
        }


of course the above test passes, but what if i have another test methods?
like this:
        [TestMethod]
        public void TestMethod2()
        {
            while (true)
            {
                Thread.Sleep(2);
                GC.Collect();
            }
        }

now if i run the both tests, supposing TestMethod1 runs before TestMethod2, the VSTestHost.exe will crash with the following Exception:

One of the background threads threw exception: System.NullReferenceException: Object reference not set to an instance of an object.
   in  DestructorTypeMock.LegacyClass.Finalize() in d:cs8DestructorTypeMockDestructorTypeMockLegacyClass.cs:line 14
Test host process exited unexpectedly.


however this is not happening if i removing the [Isolated] attribute.

You can see that this is happening from the LegacyClass destructor, the GC.Collect(); command is there only to rapidly reproduce the behavior.

the first thing i thinked about is to add the GC.SuppressFinalize(fake); call. this is helping with this specific case, but not with the following case:

    public class Program
    {
        public static void Main(string[] args)
        {
            new LegacyClass();
        }
    }

        [TestMethod]
        [Isolated]
        public void TestMethod1()
        {
            LegacyClass fake = Isolate.Fake.Instance<LegacyClass>();
            GC.SuppressFinalize(fake);
            Isolate.Swap.AllInstances<LegacyClass>().With(fake);
            Program.Main(null);
        }


the GC.SuppressFinalize will applies only to the fake that test created, not to the fake that the Main created, and the above crash and exception occures again.

i think that the Isolator api should have a "SuppressFakeFinalize" method, or at least by default prevent executing of destructors on fakes.
asked by mod (5.8k points)

3 Answers

0 votes
Hi mod,

Basically you're correct. By definition, all beehavior settings are done for objects created on that thread, and the finalizer thread calls the destructor and that's the result you see.

It looks like a bug, and what you suggest is correct - the disposable part should work correctly, as we don't need a separate API for that.

Thanks for the report, we'll let you know when the bug is fixed.
answered by gilz (14.5k points)
0 votes
Is there any plan to fix this bug in the near future?
(version 5.4.5 still have this bug)

Thanks.
answered by mod (5.8k points)
0 votes
This bug is part of Isolator's backlog as as such we plan on fixing it in a future version of Typemock Isolator.

I will update this thread when after we've fixed this bug.
answered by dhelper (11.9k points)
...