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 have a fairly simple scenario that I cannot figure out how to mock;
class ConstructorTest
    {      
        public ConstructorTest(string message)
        {
            if (String.IsNullOrEmpty(message))
                throw new ArgumentNullException();
            MyMessage = WriteMessage(message);            
        }
        private string WriteMessage(string message)
        {
            return message + " bye.";
        }
        public string MyMessage { get; set; }        
    }


I want to mock the nested private method WriteMessage. However I cannot do this, as when I create the mock with;
ConstructorTest fake = Isolate.Fake.Instance<ConstructorTest>
(Members.CallOriginal, ConstructorWillBe.Ignored);

The constuctor will never be called, but if I mock it with
ConstructorTest fake = Isolate.Fake.Instance<ConstructorTest>(Members.CallOriginal, ConstructorWillBe.Called);

Then the null arg exception will fire as the fake is created. Any ideas?
asked by pkr (3k points)

4 Answers

0 votes
You can avoid the exception thrown by passing parameters to the called c'tor with the following call:

var fake = Isolate.Fake.Instance<ConstructorTest>(Members.CallOriginal, ConstructorWillBe.Called, "someMessage");


The only problem is that WriteMessage will still get called but you can avoid this by passing parameters that make the c'tor pass without exception and then use WhenCalled to set expectation on future calls.
answered by dhelper (11.9k points)
0 votes
Unfortunatley that really is good enough. My fault for making the example too simple by using the throw exception. The real problem is that I'm mocking the inner method because it will go off and do things that are nothing to do with the unit test and that's why I want to mock them. If I have to pass something in the it will be called. This isn't a problem using the old tyle API as I'd just say to mock every call to the inner method and they'd be no initial call to the contructor to worry about.
answered by pkr (3k points)
0 votes
Currently we do not have an method that does what you suggest in the AAA.
I would suggest that you use the older API for that specific need. I will add a new feature request to a future release of Typemock Isolator.
answered by dhelper (11.9k points)
0 votes
Interesting case.
I changed the tested code to reflect your problem
public ConstructorTest(string message)
{
  MyMessage = WriteMessage(message);           
}
private string WriteMessage(string message)
{
  if (String.IsNullOrEmpty(message))
    throw new ArgumentNullException();
   return message + " bye.";
}


Here is how to do it with ReflectiveMocks

var a = MockManager.Mock<ConstructorTest>(Constructor.NotMocked);
a.AlwaysReturn("WriteMessage", "faked");

var fake = new ConstructorTest ("");


Now this will pass
Assert.AreEqual("faked", fake.MyMessage);


Here is a way to do it with an AAA hack.

var fake = Isolate.Fake.Instance<UT>(Members.CallOriginal,ConstructorWillBe.Ignored);
Isolate.NonPublic.WhenCalled(fake ,"WriteMessage").WillReturn("faked");

// call the constructor hack, make sure it is not mocked
MockManager.GetMockOf(fake).ExpectUnmockedConstructor();
// call constructor via reflection
typeof(UT).GetConstructor(new Type[] {typeof(string)}).Invoke(fake,new object[]{""});


Or you can swap the next instance as follows
var tempFake = Isolate.Fake.Instance<UT>(Members.CallOriginal,ConstructorWillBe.Ignored);
Isolate.NonPublic.WhenCalled(tempFake,"WriteMessage").WillReturn("faked");

// make sure the constructor is called for the next instance hack
MockManager.GetMockOf(tempFake).ExpectUnmockedConstructor();
Isolate.Swap.NextInstance<UT>().With(tempFake);

var fake = new UT("");
answered by eli (5.7k points)
...