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.

New to TypeMock and would appreciate some help.

I'm trying to mock an abstract class which has a method that returns an instance of another abstract class.

In my test there is a class "TestBig" which has a method called "Method" which returns an instance of "TestObject". When I try to do that, I get an exception "*** Cannot use Return in this sequence, there must be a mocked statement first Perhaps you are trying to mock a method from mscorlib" when the line "ExpectAndReturn" is executed.

Any help would be appreciated. Be gentle, I'm new to typemock. :)

using System;
using TypeMock;

namespace ScrumTest
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            try
            {
                TestBig testBig = (TestBig)RecorderManager.CreateMockedObject(typeof(TestBig));

                using (RecordExpectations recordExpectations = RecorderManager.StartRecording())
                {
                    MockManager.Init();
                    MockObject mock = MockManager.MockObject(typeof(TestObject));

                    mock.ExpectGet("Property", "ValueForProperty");
                    TestObject returnObject = (TestObject)mock.Object;

                    testBig.Method();
                    recordExpectations.ExpectAndReturn("Method", returnObject);
                }

                TestObject returnValue2 = testBig.Method();
                
                MockManager.Verify();
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

    public abstract class TestBig
    {
        public abstract TestObject Method();
        public abstract TestObject Method(string input);
    }

    public abstract class TestObject
    {
        public abstract string Property {get;}
    }
}
asked by mikkoras (880 points)

9 Answers

0 votes
Hi and welcome,

For a beginner you're not doing so bad. Mocking abstract/interfaces is a little more complex. In general you create a MockObject instance (either using the MockManager or the recorderManager) and then you set "expectations" on it. When you want to use the "real" object you access it using the MockObject.Object property.

However I think you have slightly mixed usage of Natural and Reflective mocking. In general you don't use them both in the same test. you pick one approach to use and stick with that.
Natural is kind of a "recording" mechanism in which we "record" all calls made inside a recording block expecting them to be called later on. When the "real" call arrive the mocking takes place according to what was defined in the "recording phase"

Reflective is a more explicit mechanism in which you declare specifically what you want to be mocked and how it should behave.

In any case here is your test written in both mechanisms:
[Test]
public void TestBigReflective()
{
    try
    {
        //setup phase
        MockObject mockedTestBig = MockManager.MockObject(typeof(TestBig));
        MockObject mockedTestObject = MockManager.MockObject(typeof(TestObject));

        TestObject returnObject = mockedTestObject.Object as TestObject;
        mockedTestBig.ExpectAndReturn("Method", returnObject);

        //execution phase
        TestBig testBig = mockedTestBig.Object as TestBig;
        TestObject actualReturnValue = testBig.Method();

        //checking the result
        if (actualReturnValue != returnObject)
            Console.WriteLine("Test Failed");
        MockManager.Verify();
    } 
    catch (Exception ex) 
    { 
        Console.WriteLine(ex.Message); 
    } 
}


and in Natural:

[Test]
public void TestBigNatural()
{
    try
    {
        //Setup Phase
        TestBig testBig = RecorderManager.CreateMockedObject(typeof(TestBig)) as TestBig;
        TestObject returnObject = RecorderManager.CreateMockedObject(typeof(TestObject)) as TestObject;

        using (RecordExpectations rec= new RecordExpectations())
        {
            testBig.Method();
            rec.Return(returnObject);
            // you can also write this as:
            // rec.ExpectAndReturn(testBig.Method(),ReturnObject);
        }

        //Execution phase
        TestObject actualReturnValue = testBig.Method();

        //checking the result
        if (actualReturnValue != returnObject)
            Console.WriteLine("Test Failed");
        MockManager.Verify();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}


I hope this helps.

:idea: i saw that you are writing your test in the main method. Are you using any testing framework such as nunit,mbunit...?

:idea: a lot of examples can be found under our learn tab or more specifically here https://www.typemock.com/Docs/HowTo.html
answered by lior (13.2k points)
0 votes
Is it even possible to use the natural mock if the property "Property" in the TestObject is read-only and the assumption is that the method "Method" would fill it before returning a TestObject?

No particular reason for having the test in the main-method. This is just a small test to get familiar with the TypeMock. Don't have nUnit installed yet.
answered by mikkoras (880 points)
0 votes
Yes, Using typemock you can mock read only properties.
just call the property normally in the recording block and then use Rec.Return() to specify the return value.

You can find an example in our example page.
answered by lior (13.2k points)
0 votes
Some Tips:

:arrow: if an error happens you should call MockManager.ClearAll();
catch (Exception ex)
{
   MockManager.ClearAll();
   Console.WriteLine(ex.Message);
}


:arrow: you actually should use the [VerifyMock] attribute that does this automatically for you.

:arrow: you can use Chained Natural Mocks to save creating all the objects.

:arrow: When recording a 'new' statement - the next instance of that type will be mocked.

[Test,VerifyMocks]
public void TestBigNatural()
{
    using (RecordExpectations rec= new RecordExpectations())
    {
        TestBig testBig = new TestBig(); // first instance will be mocked 
        rec.ExpectAndReturn(testBig.Method().Property,"fake"); // calls to Property will return fake
    }

    // Execution phase
    TestBig mockedBig = new TestBig(); // MAGIC - this will be mocked

    // checking the result
    string result = mockedBig.Method().Property;
    Assert.AreEqual("fake",result);
}
answered by scott (32k points)
0 votes
Well what about the following scenario:

Controller class has a method Start() which is called. Inside this method we need to get an instance of TestObject which is populated by TestBig.Method(). And the call to the TestBig.Method() is the one that we need to mock.

Difference to the previous example is that the TestBig.Method() return value would be generated via a delegate. I guess the reason for this would be that if we want a method to return a very complex method, we could use the delegate to always populate the returned object the same way regardless where it's called from.

In the following example the "rec.Return("Huh?");" line throws an exception "Cannot use Return in this sequence, there must be a mocked statement first. Perhaps you are trying to mock a method from mscorlib"

namespace ScrumTest
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Controller controller = new Controller();
            controller.Start();
        }
    }

    public class Controller
    {
        public void Start()
        {
            try
            {
                TestBig testBig = RecorderManager.CreateMockedObject(typeof(TestBig)) as TestBig;

                using (RecordExpectations recorder = new RecordExpectations())
                {
                    testBig.Method();
                    recorder.ExpectAndReturn(0, new DynamicReturnValue(BuildTestObject));
                }

                TestObject returno = testBig.Method();

                MockManager.Verify();
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }

        object BuildTestObject(object[] parameters, object context)
        {
            try
            {
                TestObject returnObject = RecorderManager.CreateMockedObject(typeof(TestObject)) as TestObject;

                using (RecordExpectations rec = new RecordExpectations())
                {
                    string temp = returnObject.Property;
                    rec.Return("Huh?");
                }
                return returnObject;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw ex;
            }
        }
    }

    public abstract class TestBig
    {
        public abstract TestObject Method();
    }

    public abstract class TestObject
    {
        public abstract string Property { get;}
    }
answered by mikkoras (880 points)
0 votes
I'm preaty sure i dont fully understand what you want to achieve.
If you can try to clarify what exactly you want to achieve by describing ion words what expected result you are aiming at.

However I'll try to answer anyway.

First the usage of ExpectAndReturn in your example is not correct.
In a recording block you can choose one of two forms:
testBig.Method();
recorder.Return(returnObject);
or
recorder.ExpectAndReturn(testBig.Method(), returnObject);

Where ReturnObject is the instance you wish the call to method to return.

Usage of DynamicReturnValue is good in case you need to return different things in different cases. (I dont think this is what you need)

I think that you want to return the same object always. This can be done by using the RepeatAlways directive
testBig.Method();
recorder.Return(returnObject).RepeatAlways();



:idea: I think that we will understand better what you need if you can show us the real code you wish to test.
answered by lior (13.2k points)
0 votes
Sorry... Can't show the real code. :(

The assumption is that TestBig and TestObject are abstract classes to which we don't have implementation as of yet.

The idea of the code is to mock the TestBig.Method() to return a filled TestObject when it's called from Controller.Start(). And TestObject has mostly read-only properties which would be filled by the TestBig.Method().

The reflective mocking below works and a filled TestObject is returned by the mocked TestBig.Method(). The natural mocking didn't work though: the code threw an exception when I was trying to set a value to the read-only property "Property".

I guess I'm trying to figure out when and how to use the reflective way and when the natural.

The real code has a method which returns a complex object structure with many read-only properties. And we want to make sure that when mocking a call to that method, the returned object is generated in a single location and the delegate seems like a way to go. Moving the mocked object creation to a separate method means less duplicate work and the original code remains cleaner.

I know it's vague. NDA's... But hopefully that cleared at least some of it.

using System;
using TypeMock;

namespace ScrumTest
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Controller controller = new Controller();
            controller.Start();
        }
    }

    public class Controller
    {
        public void Start()
        {
            try
            {
                TestBig testBig = RecorderManager.CreateMockedObject(typeof(TestBig)) as TestBig;

                using (RecordExpectations recorder = new RecordExpectations())
                {
                    testBig.Method();
                    recorder.ExpectAndReturn(0, new DynamicReturnValue(BuildTestObject));
                }

                TestObject returno = testBig.Method();

                MockManager.Verify();
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }

        object BuildTestObject(object[] parameters, object context)
        {
            try
            {
                MockObject returnObject = MockManager.MockObject(typeof(TestObject));
                returnObject.ExpectGetAlways("Property", "ValueForProperty");
                return returnObject.Object as object;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                throw ex;
            }
        }
    }

    public abstract class TestBig
    {
        public abstract TestObject Method();
    }

    public abstract class TestObject
    {
        public abstract string Property { get;}
    }
}
answered by mikkoras (880 points)
0 votes
The idea of the code is to mock the TestBig.Method() to return a filled TestObject when it's called from Controller.Start(). And TestObject has mostly read-only properties which would be filled by the TestBig.Method().

I understand that you want to mock the call to TestBig.Method() and return a mocked TestObject. Since TestObject has no real implementation you will need to use a mock instead, mocking all calls made on him during the execution of the test.
here is a way to do it: (without the expectation on TestObject)
using (RecordExpectations rec = new RecordExpectations())
{
  TestObject mockedTestObject = RecorderManager.CreateMockObject(typeof(TestObject));
  TestBig mockedTestBig = RecorderManager.CreateMockObject(typeof(TestBig ));
  rec.ExpectAndReturn(mockedTestBig.Method(),mockedTestObject);
}

The reflective mocking below works and a filled TestObject is returned by the mocked TestBig.Method(). The natural mocking didn't work though: the code threw an exception when I was trying to set a value to the read-only property "Property".

This shouldnt happen what was the exception that you were getting? and where exactly were you getting it (I'm not sure if you got it when trying to mock the property or in the recording block see below)

I guess I'm trying to figure out when and how to use the reflective way and when the natural.

Natural and Reflective are basically two different ways to achieve the same. Some people find natural easier to understand and work with and some reflective. Basically there are some things that you can achieve only using reflective such as mocking private methods and such, but using natural has the advantage of strong typing and is eaiser to maintain later using common refactoring tools.

The real code has a method which returns a complex object structure with many read-only properties. And we want to make sure that when mocking a call to that method, the returned object is generated in a single location and the delegate seems like a way to go. Moving the mocked object creation to a separate method means less duplicate work and the original code remains cleaner.

Naturally, but you dont need to use a delegate for this. You can just move the creation to a regular method. I would even say to store the created mock into a memebr variable using it as a return value later on when needed. something in the spirit of:
void MockCreation()
{
  //create 
  mockedTestObject = MockManager.MockObject(typeof(TestObject));//where mockedTestObject is a memebr variable
  //now need to setup needed expectations
}

void TestMethod()
{
  using (RecordExpectations rec = new RecordExpectations())
  {
    TestBig mockedTestBig = RecorderManager.CreateMockObject(typeof(TestBig ));
    rec.ExpectAndReturn(mockedTestBig.Method(),mockedTestObject);
  }  
}

:idea: Most testing frameworks has a setup mechanims which allows you to run a given method at the start of each test

I know it's vague. NDA's... But hopefully that cleared at least some of it.

If you like we can take if offline (and even sign an NDA if needed.)

using (RecordExpectations recorder = new RecordExpectations())
{
testBig.Method();
recorder.ExpectAndReturn(0, new DynamicReturnValue(BuildTestObject));
}

This piece of code is not right
it should be:
using (RecordExpectations recorder = new RecordExpectations()) 
{ 
    testBig.Method(); 
    recorder.Return(new DynamicReturnValue(BuildTestObject));
} 

or
using (RecordExpectations recorder = new RecordExpectations()) 
  { 
    recorder.ExpectAndReturn(testBig.Method(), new DynamicReturnValue (BuildTestObject)); 
  } 

the way it is written you'll get an exception (you actually record two calls with only one return value)

Hope this help
let me know if you have any more questions
answered by lior (13.2k points)
0 votes
:idea: You cannot record or use mocks within a DynamicReturnValue delegate.
answered by scott (32k points)
...