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
Hi,

I am trying to mock calls to a private member object. The code below is a made up example I created to reproduce the problem. I am testing Car.Start() and want to mock calls to Car.myEingine.Start() to test what happens if the method returns false instead of true.

The test code below shows 3 experiments that failed: (1) I cannot reach the private class because of its protection level, (2) using reflective mocks does not support chaining and (3) mocking the private accessor does not mock the actual class...

Any help is greatly appreciated,

Thanks,
Wael


CLASS UNDER TEST:

public class Car
{
private class Engine
{
public bool Start()
{
return true;
}
}

private Engine myEngine = new Engine();

public bool Start()
{
return myEngine.Start();
}
}



UNIT TEST CODE:

[TestMethod()]
public void StartTest()
{
MockManager.Init();
Car target = new Car();

// EXPERIMENT 1: Does not work due to protection level of Car.Engine
//Mock mock = MockManager.MockAll(typeof(TestLibrary.Car.Engine));
//

// EXPERIMENT 2: Chaining: Throws exception: No method "Engine.Start" on class Car
//Mock mock = MockManager.MockAll(typeof(TestLibrary.Car));
//mock.ExpectAndReturn("Engine.Start", (bool)false);
//

// EXPERIMENT 3: Mock the private accessor??
// Does not mock the class under test
//TestLibrary_Car_EngineAccessor pa = new TestLibrary_Car_EngineAccessor(target);
//using (RecordExpectations recorder = RecorderManager.StartRecording())
//{
// recorder.ExpectAndReturn(pa.Start(), (bool)false);
//}
//

bool expected = false; bool actual;
actual = target.Start();

Assert.AreEqual(expected, actual, "Test Failed");
MockManager.Verify();
}
asked by hemdanw (1.7k points)

2 Answers

0 votes
Hi

Unfortunately you can not mock private inner class directly. :(
There is however workaround by using reflection.

Here is how you can do it:
        [TestMethod()] 
        public void StartTest()
        {
            MockManager.Init();
            Car target = new Car();
            new ReflectionPermission(PermissionState.Unrestricted).Demand();

            Type t = typeof(Car).Assembly.GetType("Car+Engine", true);
            Mock mock = MockManager.MockAll(t);
            mock.ExpectAndReturn("Start", false);

            bool expected = false;
            bool actual;
            actual = target.Start();

            Assert.AreEqual(expected, actual, "Test Failed");
            MockManager.Verify();
        }


Note the strange line
Type t = typeof(Car).Assembly.GetType("Car+Engine", true);


This is the way you can reach your inner class using reflection
Another thing to notice is that if the Car class is inside a namespace
the code should be:
Type t = typeof(YourNameSpace.Car).Assembly.GetType("YourNameSpace.Car+Engine", true);


One last thing.
To see the types names inside the assembly use:

Type t = typeof(Car).Assembly.GetType("Car+Engine", true);
Type []tArr = t.Assembly.GetTypes();


You Then can look in the debugger at tArr for the names inside the assembly.
Hope it helps.
answered by ohad (35.5k points)
0 votes
Version 3.6 supports mocking private accessors and can be used to solve this issue
answered by scott (32k points)
...