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 using Natural Mocks (still really cool!). In one particular test method, typemock is not mocking one of the calls I've asked it to mock.. my test method ends up calling through to the real method, which is not what I wanted it to do.

My TestMethod:

            using (RecordExpectations r = RecorderManager.StartRecording())
            {
                Deliver _deliver = new Deliver();
                _deliver.Prep();
                _deliver.Mature();
                _deliver.Validate();
                _deliver.Exec();
            }

            target.Execute();


tests a function in my production code that essentially looks like this (where _deliver in this class is a private member type Deliver):

           Execute() {
               _deliver.Prep();
               _deliver.Mature();
               _deliver.Validate();
               _deliver.Exec();
            }


When the test method calls Execute (target.Execute), Execute calls _deliver.Prep() -- which I expect to be Mocked, but it is not.

Looking at the TypeMock traces, it Declares an expectation for Prep (I see "Expect CCDeliverOperation.Deliver.Prep() 1 Time). The first call it seems to get is "CCDeliverOperation.Deliver.Prep()". After a few more unexpected calls, the exception from the real Prep occurs and the test ends. What is strange is that in the tree view, it lists "Prep (1)" under "Unmocked Instance -1". In "Instance 0" it lists "Prep (0/1)".

So how can the Prep be both called and not recorded? Thus my confusion.. What am I doing wrong? I have no other classes called Deliver and have verified Deliver means CCDeliverOperation.Deliver in all cases.

I'm using the Enterprise Edition of the product.. and Of course, I'm Init'ing my MockManager.

Thanks for the help!

-Eric
________
FIRST GENERATION SUBARU LEGACY
asked by erichorne (3.4k points)

7 Answers

0 votes
Hi,
From your trace output, it seems that you have more then one instance of Deliver.

In the test the Natural Mock is expecting a new instance of Deliver, but in the production code _deliver is already created (and not mocked).
My guess is that _deliver is created before the mocks are recorded (this is the Unmocked Instance -1, where minus indicates that the instance was alive before mocking started).

There are two solutions.
1. record the expectations before the creation of _deliver.
2. mock all the instances of Deliver by using: r.MockAllInstances = true; (See Mocking Future Objects)
answered by scott (32k points)
0 votes
There are two solutions.
1. record the expectations before the creation of _deliver.
2. mock all the instances of Deliver by using: r.MockAllInstances = true; (See Mocking Future Objects)


I just realized that my test method DOES NOT perform a new Deliver within the using syntax. _deliver = new Deliver() occurs before the using statement like so:

                Deliver _deliver = new Deliver();
            using (RecordExpectations r = RecorderManager.StartRecording())
            {
                _deliver.Prep();
                _deliver.Mature();
                _deliver.Validate();
                _deliver.Exec();
            }

            target.Execute();


Sorry for the typo..

Ok Solution number 1: I don't know how to capture calls into Deliver using Natural Mocks without creating an instance first. I don't think I understand what you're suggesting. If I put the _deliver = new Deliver() AFTER the using statement, I'll get a NullReferenceException because _deliver isn't set to anything. If I make it so that target isn't created until after the using, the call to Prep is not mocked. target does, in fact, create a Deliver instance.

Solution number 2: I tried using MockAllInstances = true, but it did not help. Prep is still not being Mocked.

I also tried first gen mocking (Un-natural mock?) and I could not get it to mock the call to Prep.

Thanks for the help!

-Eric
________
MULTIPLE SCLEROSIS ADVICE
answered by erichorne (3.4k points)
0 votes
creating the instance BEFORE the using wil mock LIVE Objects. i.e. you will be mocking the _deliver created in the test code.

I don't know how many instances you production code creates. But if it is one, you should actually create the object in the test code.
Here is an example:
using (RecordExpectations r = RecorderManager.StartRecording())
{
   // mock next instance
   Deliver _mockedDeliver = new Deliver();
   _mockedDeliver .Prep();
   _mockedDeliver .Mature();
   _mockedDeliver .Validate();
   _mockedDeliver .Exec();
}

target.Execute(); 

In any case if you export the Trace Log and send it to me I can find the error.
answered by scott (32k points)
0 votes
creating the instance BEFORE the using wil mock LIVE Objects. i.e. you will be mocking the _deliver created in the test code.


Interesting.. I was trying to be smart and pre-create the Deliver object (_deliver) that the target (a DeliverCommand object) would ultimately create. It sounds like I can't create either object in the TestInitialize method, but that I must create them in the testmethods.

When I do this, my tests pass (yay!) and more importantly, Prep, along with all the other methods are mocked. In other tests for other classes, I've been able to get away with pre-creating the objects in TestInitialize, but none of them created internal objects I wanted mocked.

If I create the _deliver within the using, but create the target prior to the using, the Deliver methods in target do not get mocked. Even if I turn on r.MockAllInstances after the _deliver creation. Is that expected behavior?

Is there a way that I can pre-create target (in my TestInitialize function) and still mock the Deliver object it creates for itself internally?
answered by erichorne (3.4k points)
0 votes
Yes,
The easy way is if you can get a hold of the instance.
Suppose you have a targer.Deliver property you can then use the Live instance mocking
Deliver _mockedDeliver = target.Deliver;
using (RecordExpectations r = RecorderManager.StartRecording())
{
   _mockedDeliver .Prep();
   _mockedDeliver .Mature();
   _mockedDeliver .Validate();
   _mockedDeliver .Exec();
}

target.Execute();


I think that MockAllInstances should work in your case. Please send me the Trace output so that I can check it.
answered by scott (32k points)
0 votes
Thanks Scott. I got it fixed. I can still send you a trace log if you want to see it, but I'm out of the woods at this point.

I now have a better understanding of Natural Mocks :) They mock specific instances, not whole classes. And it sounds like MockAllInstances mocks instances created after that value is set.

For the benefit of others... in my TestInitialize function, I create a target (DeliverCommand) and, using a private accessor, assign target's created Deliver to my _deliver in the test. That makes TypeMock (and me!) much happier.

Thanks again for all the support and explanation, Scott! I'm always impressed with you guys.

-Eric
answered by erichorne (3.4k points)
0 votes
Thanks Eric,
Natural mock can mock static (non instance) methods too. 8)
MockAllInstances mocks both past and future mocks (I rerun that test and it works fine). 8)

:idea: What might be happening is that other code in your initializer calls _driver.Prep() and thus the next calls are not mocked.
You can see this in the tracer, and you can support this by one of the following:
1. Use r.Repeat or r.RepeatAlways.
2. Start mocking on the object when needed for test

I perfer the second ,way which is what you did, as this will make the tests less fragile to code in the initializer.
answered by scott (32k points)
...