Welcome to Typemock Answers. Here you can ask and receive answers from other community members. And if you liked or disliked an answer or thread: react with an up- or downvote Enjoy!

Prevent a virtual method from being called from a it's singleton child class

0 votes
As you may look at the follownig code, here is the scenario and my goal :
 
Goal  : 
  1.  Prevent ScratchFoot() method from being called, so we need to fake Godzilla so it deosn't call tickle()
  2.  Check if startMovie() was called.
 
 
 Notes : 
  1.  tickle is a virtual method and only exists in the Godzila class.
  2.  in our system under test we're calling MakeHimLaugh() method.
 
 
namespace JurassicEra
{

	public abstract class Godzilla
	{
		public Godzilla()
		{
			// some unrelated logic 
		}

		protected virtual byte[] tickle(object feather , object water)
		{
			if(feather == null)
			{
				return null;
			}
			return this.ScratchFoot(feather, water);
		}
	}
}

namespace InstagramEra
{
	public sealed class Lizard : Godzilla
	
	private static Lizard instance;
	private static object syncRoot = new object();
	
	public static Lizard getInstance()
	{
	    if (instance == null)
		{
			lock (syncRoot)
			{
				if (instance == null)
				{
					instance = new Lizard();
				}
			}
		}
		return instance;
	}
	
	private Lizard()
	{
	}
	
	public void MakeHimLaugh(object feather , object water)
	{
		Theater theater = new Comedy();
		object poorLizard = this.tickle(feather, water);
		
		theater.startMovie();		
	}	
}
 *** Please save yourself and me the time to argue that why an abstract class has public constructor and other design challenges. This is my current structure and I'm only here to test it.
 
 
 Secnarios :
 
  
 I tried all the following scenarios, and non of them worked for me, meaning in all 3 cases tickle() was called.
 
 what I did; I'm passing null for feather, so this method will return null so it won't get to call ScratchFoot method.
 
 
 
 
public void CheckIfMovieStarted()
{
	var fakeGodzilla = Isolate.Fake.AllInstances<Godzilla>();	
	Isolate.NonPublic.WhenCalled(fakeGodzilla, "tickle").WillReturn(null);	
}

public void CheckIfMovieStarted()
{
	Isolate.Invoke.StaticConstructor<Lizard>();
	var fakeLizard = Lizard.getInstance();	
	Isolate.NonPublic.WhenCalled(fakeLizard, "tickle").WillReturn(null);	
}

public void CheckIfMovieStarted()
{
	var fakeLizard = Lizard.getInstance();	
	Isolate.NonPublic.WhenCalled(fakeLizard, "tickle").WillReturn(null);	
}

 

Thank you 
 
 
 
 
 
 
 
 
 
 
 
asked Nov 21 by aringan (160 points)

1 Answer

0 votes

Hey aringan,

In order to prevent ScratchFoot() method from being called you can use "IgnoreCall()":

var fakeGodzilla = Isolate.Fake.AllInstances<Godzilla>();
Isolate.NonPublic.WhenCalled(fakeGodzilla, "tickle").IgnoreCall();

About verifying startMovie() was called, basically you can use Isolate.verify.WasCalledWithAnyArguments() , but in order to give you a more accurate answer, can you provide me more information about Theater and Comedy classes? 

 

answered Nov 21 by SapirTypemock (1,550 points)

Thank you for your respond. 

I did the following and it worked for me :

public void CheckIfMovieStarted()
{
    Isolate.Invoke.StaticConstructor<Lizard>();
    var fakeTheater = Isolate.Fake.AllInstances<Theater>(); 
    Isolate.Verify.WasCalledWithAnyArguments(() => fakeTheater.startMovie());
  
}

 

NOTE : I did'nt use IgnoreCall() , since "tickle" method returns an object. please correct me if I am wrong.

 

Thank you  

 

Hey aringan,

You're right. You shouldn't use IgnoreCall() on non-void methods. 

The fact that this possibility exists is a mistake in our system, and we will fix it as soon as possible.

Meanwhile, in order to prevent ScratchFoot() method from being called you can do this:

var lizard = Lizard.getInstance();

Isolate.NonPublic.WhenCalled(lizard, "tickle").DoInstead(c => 
{
            c.Parameters[0] = null;
            c.WillCallOriginal();
});

That way, when you call tickle(), feather will be null and ScratchFoot() will not be called. 

...