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
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
I'm mocking a class that has a destrcutor. During some of the test I do not expect my tested code to dispose of the mocked object, and therefore I do not expect the destructor to be called. However, when the object is mocked, TypeMock creates a real .NET instance of the object, which is automatically disposed by the GC after the object gets out of scope.

A call to GC.SuppressFinalize on the object may help, but I was able to do it only when using reflective mocks. With reflective mocks it's very simple: I call GC.SuppressFinalize on the mocked instance that I can get from the MockedInstance property of my mock object.

When using natural mocks, it seems that I do not have access to that instance. I tried calling GC.SuppressFinalize on all the instances received when calling MockManager.GetMockes<MyMockedType>(), but it did not help.

Is there a way to do it, or do I have to give up natural mocks when mocking objects with destructors?
asked by avnerc (600 points)

13 Answers

0 votes
Hi Avner

You can access the the Mock controller using the following methods of RecorderManager:
GetLastRecordedMock()
GetLastRecordedMockedObject()
GetMockOf()

That said, it might be a good feature of the Isolator to suppress the finalizer on mocked instance.
answered by ohad (35.4k points)
0 votes
Is the feature has been done since the last post?

I got the same problem.
answered by pierre-luc (3.3k points)
0 votes
Hi,

Can you please give a concrete example?
Using the AAA api this should not be a problem since every method is faked by default.
answered by ohad (35.4k points)
0 votes
Hi,
When I try to dispose of sc (see below), Dipose() isn't called (and that's normal since it's faked object).
But, when GC try to clean up, it calls the finalizer of sc and than Dispose(bool) is called. These functions aren't supposed to be faked?

        [TestMethod]
        [Isolated]
        public void Test_DisposeOnFake()
        {
            var fakeSimpleClass = Isolate.Fake.Instance<SimpleClass>();
            Isolate.WhenCalled(() => fakeSimpleClass.GiveMe8()).WillReturn(7);
            Isolate.Swap.AllInstances<SimpleClass>().With(fakeSimpleClass);

            var sc = new SimpleClass() { Number = 65 };
            sc.Dispose();
        }


    public class SimpleClass : IDisposable
    {
        public SimpleClass()
        {
            m_number = 44;
        }

        ~SimpleClass()
        {
            Dispose(false);
            // System.Diagnostics.Debug.Assert(false);
        }

        public int GiveMe8()
        {
            return 8;
        }

        private int m_number = 9;
        public int Number
        {
            get { return m_number; }
            set { m_number = value; }
        }

        #region IDisposable Members

        protected void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Code to dispose the managed resources of the class
            }
            else
            {
                throw new Exception("Not supposed to dispose a faked object.");
            }
            // Code to dispose the un-managed resources of the class
        }


        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
answered by pierre-luc (3.3k points)
0 votes
Hi,

Thanks for the repro. We'll check it out and get back to you with an answer.
answered by ohad (35.4k points)
0 votes
Did you find a solution or a workaround?
answered by pierre-luc (3.3k points)
0 votes
Hi,

I have verified that it's a bug. It happens since the object is collected by the garbage collector outside the scope of the test.

As a workaround, you can call GC.SuppressFinalize() on the objects.

[TestMethod]
[Isolated]
public void Test_DisposeOnFake()
{
    var fakeSimpleClass = Isolate.Fake.Instance<SimpleClass>();
    Isolate.WhenCalled(() => fakeSimpleClass.GiveMe8()).WillReturn(7);
    Isolate.Swap.AllInstances<SimpleClass>().With(fakeSimpleClass);

    var sc = new SimpleClass() { Number = 65 };
    sc.Dispose();
    GC.SuppressFinalize(sc);
    GC.SuppressFinalize(fakeSimpleClass);
}


We'll update on this thread when the bug fixed.

Regards,
Elisha,
Typemock Support
answered by Elisha (12k points)
0 votes
I need to do a SuppressFinalize on sc and fakeSimpleClass?
Are they not supposed to be the same object?
Even if I used Swap.AllInstance?
answered by pierre-luc (3.3k points)
0 votes
Hi,

This is correct, on both instances SuppressFinalize() should be called. What happens when calling Swap.AllInstances() is that the behavior of the created instances is swapped. The actual instances are different and therefor the garbage collector will call both finalizers.

Regards,
Elisha,
Typemock Support
answered by Elisha (12k points)
0 votes
Ok,
But what should I do when I don't have access to the new instance?

In my example, I have access to the mocked instance, but if the new SimpleClass is made in another class. How can I get access to that instance?

Do I have to use MockManager.GetMockes<MyMockedType>()?
answered by pierre-luc (3.3k points)
...