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,

I need to mock internal classes, how to do it via Natural Mock and/ or reflective mock?
________
buy solo vaporizer
asked by nsoonhui (59.1k points)

5 Answers

0 votes
Hi,

Here's how to do it in both ways.

    public class ExternalClass
    {
        public int GetExternal()
        {
            InternalClass ic = new InternalClass();
            return ic.GetInternal();
        }
        internal class InternalClass
        {
            internal int GetInternal()
            {
                return 3;
            }
        }
    }

    [TestFixture]
    public class TestClass
    {
        [Test]
        public void TestReflective()
        {
            Mock mock = MockManager.Mock(typeof(ExternalClass.InternalClass));
            mock.ExpectAndReturn("GetInternal", 5);

            ExternalClass ec = new ExternalClass();
            Assert.AreEqual(5, ec.GetExternal());
            MockManager.Verify();
        }

        [Test]
        public void TestNatural()
        {
            using (RecordExpectations rec = RecorderManager.StartRecording())
            {
                ExternalClass.InternalClass ic = new ExternalClass.InternalClass();
                rec.ExpectAndReturn(ic.GetInternal(), 5);
            }

            ExternalClass ec = new ExternalClass();
            Assert.AreEqual(5, ec.GetExternal());
            MockManager.Verify();

        }
    }


Note that in order for the tests to compile, the accessibility modifier of the internal needs to be correct. For private classes or out-of-assembly classes, you'll either need to use MS private accessors.
answered by gilz (14.5k points)
0 votes
Hi,

Here's how to do it in both ways.

    public class ExternalClass
    {
        public int GetExternal()
        {
            InternalClass ic = new InternalClass();
            return ic.GetInternal();
        }
        internal class InternalClass
        {
            internal int GetInternal()
            {
                return 3;
            }
        }
    }

    [TestFixture]
    public class TestClass
    {
        [Test]
        public void TestReflective()
        {
            Mock mock = MockManager.Mock(typeof(ExternalClass.InternalClass));
            mock.ExpectAndReturn("GetInternal", 5);

            ExternalClass ec = new ExternalClass();
            Assert.AreEqual(5, ec.GetExternal());
            MockManager.Verify();
        }

        [Test]
        public void TestNatural()
        {
            using (RecordExpectations rec = RecorderManager.StartRecording())
            {
                ExternalClass.InternalClass ic = new ExternalClass.InternalClass();
                rec.ExpectAndReturn(ic.GetInternal(), 5);
            }

            ExternalClass ec = new ExternalClass();
            Assert.AreEqual(5, ec.GetExternal());
            MockManager.Verify();

        }
    }


Note that in order for the tests to compile, the accessibility modifier of the internal needs to be correct. For private classes or out-of-assembly classes, you'll either need to use MS private accessors.

Sorry for not making myself clear, when I say that I want to mock internal class, I don't mean that I want to mock internal class that is within a public class. I want to mock
    internal class InternalClass
    {
        public int GetInternal()
        {
                   return 3;
        }

    }


but not
    public class ExternalClass
    {
        public int GetExternal()
        {
            InternalClass ic = new InternalClass();
            return ic.GetInternal();
        }
        internal class InternalClass
        {
            internal int GetInternal()
            {
                return 3;
            }
        }
    }

________
Honda Unicorn history
answered by nsoonhui (59.1k points)
0 votes
Hi,

Well, we're going back to the accessibility modifier issue I referred to. If the class is internal it can be accessible only by classes (and tests) within that assembly.

Since we usually keep our tests outside the assembly, the internal class is not visible to the tests and cannot be directly tested. So here are a couple of options.

Option 1: mark the original class' assembly with the attribute "InternalsVisibleTo", with the name of the calling assembly (which in our case contains the tests). All internal types and methods would appear to be public for the tests, and therfore mockable.
Note that if your class assembly is signed, you will also have to sign the test assembly, and put the public key of the tests assembly in the aforementioned "InternalsVisibleTo" attribute.

[assembly: InternalsVisibleTo("TestDLL, PublicKey=00240000...")]


Option 2: In VS2005 either Developer or Tester addition you can use the "Create Private Accessor" option, which generates code for, well, private accessor. The generated class (which is obviously not the original class name) does have the same interface of the original class. When you have the accessor class, you can mock it instead of the original class.
In VS2008, by the way, the feature is accessible in the Professional version and up.

Let me know if this helps, or if you need further assistance.
answered by gilz (14.5k points)
0 votes
Hi,

Well, we're going back to the accessibility modifier issue I referred to. If the class is internal it can be accessible only by classes (and tests) within that assembly.

Since we usually keep our tests outside the assembly, the internal class is not visible to the tests and cannot be directly tested. So here are a couple of options.

Option 1: mark the original class' assembly with the attribute "InternalsVisibleTo", with the name of the calling assembly (which in our case contains the tests). All internal types and methods would appear to be public for the tests, and therfore mockable.
Note that if your class assembly is signed, you will also have to sign the test assembly, and put the public key of the tests assembly in the aforementioned "InternalsVisibleTo" attribute.

[assembly: InternalsVisibleTo("TestDLL, PublicKey=00240000...")]


Option 2: In VS2005 either Developer or Tester addition you can use the "Create Private Accessor" option, which generates code for, well, private accessor. The generated class (which is obviously not the original class name) does have the same interface of the original class. When you have the accessor class, you can mock it instead of the original class.
In VS2008, by the way, the feature is accessible in the Professional version and up.

Let me know if this helps, or if you need further assistance.

Too bad, I think neither of the options are feasible simply because I am still using vs.net 2003
________
jugalettes
answered by nsoonhui (59.1k points)
0 votes
In that case, you can only use reflective mocks:

MockObject mo = MockManager.MockObject(Type.GetType("ExternalClass+InternalClass"));
answered by paulo.morgado (11k points)
...