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
I've been attempting to mock 2 classes to test a set of code. Part of the test results in one mocked method calling another. It doesn't work out.

This example reproduces the problem.

   class A
   {
      public string Do()
      {
         return "Original Behaviour";
      }
   }

   class B
   {
      public string Do()
      {
         return new A().Do();
      }
   }

   [TestClass]
   public class UnitTest2
   {
      [TestMethod]
      public void Test()
      {
         MockObject<A> mockA = MockManager.MockObject<A>();
         mockA.AlwaysReturn("Do", "Mocked Behaviour");

         Console.WriteLine(mockA.Object.Do()); //"Mocked Behaviour"

         B mockB = Isolate.Fake.Instance<B>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
         Isolate.WhenCalled(() => mockB.Do()).DoInstead(callContext =>
         {
            return mockA.Object.Do();
         });

         Console.WriteLine(mockB.Do()); //"Original Behaviour" -- Expected "Mocked Behaviour"
      }
   }


The first Console.WriteLine outputs "Mocked Behaviour", but the second outputs "Original Behaviour". Is this expected behavior or a bug? Maybe I'm doing something wrong here?
asked by Samuel (1.1k points)

3 Answers

0 votes
Hi Samuel,

The reason the second call returns the original value instead of the fake is due to the context in which it's called. The second call causes the DoInstead to execute and inside it the behavior is not faked. Therefor, the call to mockA inside the DoInstead uses the original method.

This is the expected behavior, but since it seems confusing in the example we will consider changing it. It's not a common case since usually there is no need to call a fake inside the DoInstead.

Can you please describe what are you trying to test? I'll try to help with it.

Best Regards,
Elisha
Typemock Support Team
answered by Elisha (12k points)
0 votes
Thanks Elisha.

The example isn't a direct match with the problem that I was trying to solve.

In the actual code that I was working with, class A above would correspond to a rather large configuration and state management feature. We mock this entire object. Class B would correspond to an object that interacts with a remote service. This is also mocked.

The problem came up because the remote interaction code was mocking a method to create and return an object of a 3rd type. That type's constructor uses the mocked configuration object and a mocked property on it. I wanted a non-mocked version of that 3rd type.

In the end, I created an object of the 3rd type ahead of time and returned it in the mocked remote interaction code. So I've worked around this issue.
answered by Samuel (1.1k points)
0 votes
Hi Samuel,

I think that what you did is the correct approach. Basically, if you want to return a real object, you need to create it, and you can pass it the fake configuration object (which, as I understand it, is what you did).

Thanks for reporting (and that you found a workaround)
answered by gilz (14.5k points)
...