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 all,

I've been trying to get things started with Typemock for a couple of hours, however, I still don't get it. Suppose I have the following simple class (simplified example):

public class SomeClass
{
  public string SomeMethod()
  {
    string returnString = string.Empty;
    OtherClass otherClass = new OtherClass( "some param" );
    returnString = otherClass.SomeOtherMethod();
    return returnString;
  }
}


Now what I'd like to do is to fake the creation of otherClass and the call to otherClass.SomeOtherMethod - how would I do that?

What I've tried is:

[TestMethod]
public void TestMethod1()
{
  // Arrange
  SomeClass fake = Isolate.Fake.Instance<SomeClass>();
  OtherClass otherClass = Isolate.Fake.Instance<OtherClass>();
  Isolate.Swap.NextInstance<OtherClass>().With( otherClass );
  
  Isolate.WhenCalled( () => fake.SomeMethod() );
  Isolate.WhenCalled( () => otherClass.SomeOtherMethod() );

  // Act
  string result = fake.SomeMethod();

  // Assert
  Isolate.Verify.WasCalledWithAnyArguments( () => fake.SomeMethod() );
  Isolate.Verify.WasCalledWithAnyArguments( () => otherClass.SomeOtherMethod() );
}


The test always fails with an exception that a call to otherClass.SomeOtherMethod was expected but did not happen - any ideas what's wrong with my code?

Thanks in advance

G.
asked by gorgsenegger (680 points)

1 Answer

0 votes
I think the problem you're running into is that you're mocking too much. If you read the arrange part of the test in natural language, it says:

Make a fake version of SomeClass. Make a fake version of OtherClass. When you call SomeMethod on the fake version of SomeClass, don't really call it, just fake it. When you call SomeOtherMethod on the fake version of OtherClass, also don't really call it.

Then when you're running the test, you're testing the fake version of SomeClass, not a real version... and when you call the SomeMethod on the fake, it's doing nothing - because that's what you told it to do.

It's pretty common to want to mock a ton of stuff when first starting out, but a good rule to follow is 'mock as little as absolutely necessary.'

Another good rule is to make sure you are as explicit as possible. For example, the line...

Isolate.WhenCalled( () => otherClass.SomeOtherMethod() );


Sets up an expectation, but doesn't really DO anything. What do you want it to do? Return an expected value? Call the original method? I think the default behavior is to call the original, which, since you've set it up to be a fake, means it'll return null. Might be better to do something like this:

Isolate.WhenCalled( () => otherClass.SomeOtherMethod() ).WillReturn("expectedValue");


Two reasons for that: First, when you read through the code, you'll know exactly what's going on because the statement is very explicit so there's no guessing at what the behavior will be. Second, now that you have a fixed value that will be returned, you can integrate that value into your tests. Rather than test if a SomeOtherMethod was called, you can test whether the return value of the larger function was as expected given that faked value.

In this case, the test should be:

[TestMethod]
public void TestMethod1()
{
  // Arrange
  OtherClass otherClass = Isolate.Fake.Instance<OtherClass>();
  Isolate.Swap.NextInstance<OtherClass>().With( otherClass );
 
  Isolate.WhenCalled( () => otherClass.SomeOtherMethod() ).WillReturn("expectedValue");

  // Act
  SomeClass real = new SomeClass();
  string result = real.SomeMethod();

  // Assert
  Assert.AreEqual("expectedValue", result);
  // Optionally, you can verify the call to SomeOtherMethod, but since
  // that's proven already by the result coming back with the expected
  // value, it's redundant.
  Isolate.Verify.WasCalledWithAnyArguments( () => otherClass.SomeOtherMethod() );
} 


I didn't actually compile this, but it looks right in my mental compiler and should work.

Hope that helps.
-T
answered by tillig (6.7k points)
...