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!

Typemock looks quite powerful and flexible, but due to lack of experience I cannot find easy way to treat the following problem.

Assume I have a method:
public Result DoUsefulThing(string s1, string s2, string s4, string s5)
{
   var local1 = obj1.Get(s1);
   if (!obj1.Check(local1))
      return new Result("something undesirable");

   var local2 = obj2.Get(s2);
   if (!obj2.Check(local2))
      return new Result("something quite bad");
   
   var local3 = obj3.Get(s3);
   if (!obj3.Check(local3))
      return new Result("something very bad");

   var local4 = obj4.Get(s4);
   if (!obj4.Check(local4))
      return new Result("something terrible");

   var local5 = obj5.Get(s5);
   if (!obj5.Check(local5))
      return new Result("something horrible");

   var value = this.Calculation(local1, local2, local3, local4, local5);
   if (this.IsError(value))
      return new Result("the last step resulted in an error!");

   return new Result{ Value = value, Msg = "Success"};
}

It (i.e. method DoUsefulThing) depends on a number of various objects and making calls to their methods (objN.Get, objN.Check, this.Calculation, this.IsError).

The obj1..obj5 are created and correctly formed before the call to method DoUsefulThing (some created in constructor, some in other methods, some are passed from elsewhere).

What I want is to make a number of tests, where, say, calls to obj1, obj2, obj4, obj5 methods are remain original, but the result of the call to obj3.Get, obj3.Check and Calculation is substituted by my code. I suppose this is doable with Typemock framework, althoug I don't know how.

Could you explain me please, how do I achieve this? Thank you in advance!
asked by tinynick (1.2k points)

4 Answers

0 votes
If I understand correctly all you want is that the DoUsefulThing will be called but some methods such as obj1.Check won't be called?

it seems that obj1..obj5 are fields in your class so you need to replace them with a fake object created with CallOriginal with only the desired function set to return a predefined value.
For Example obj1 would be faked:
var fakeObj1 = Isolate.Fake.Instance<Obj1Class>(Members.CallOriginal);
Isolate.WhenCalled(() => fakeObj1.Check(null)).WillReturn(true);
// Now we need to use a setter or some method to replace obj1
obj1 = fakeObj1;

// if obj one wasn't a field or we initialize the parent class we can use future fakes
Isolate.Swap.NextInstance<Obj1Class>().With(fakeObj1);
answered by dhelper (11.9k points)
0 votes
If I understand correctly all you want is that the DoUsefulThing will be called but some methods such as obj1.Check won't be called?


Yes, exactly. Instead of call I need to don nothing and provide a handmade value.

it seems that obj1..obj5 are fields in your class so you need to replace them with a fake object created with CallOriginal with only the desired function set to return a predefined value.


Setting the falue isn't very suitable, because the class has only default constructor with private fields
public class MyClass
{
   private TestFoo obj1;
   private TestFoo obj2;
   private TestFoo obj3;
   private TestFoo obj4;
   private TestFoo obj5;

   public MyClass()
   {
      obj1 = Factory.Create(1);
      obj2 = Factory.Create(2);
      obj3 = Factory.Create(3);
      obj4 = Factory.Create(4);
      obj5 = Factory.Create(5);
   }
   public Result DoUsefulThing(
      string s1, string s2, string s3, string s4, string s5)
   { ... }
}

(Actualy not exactly that straigtforward, the code is just "total residue" and demonstrates the problem).

As I understand, the test picking obj3 methods should be like that:
[Test]
public void Scenario3()
{
   var fakeObj1 = Isolate.Fake.Instance<MyClass>(Members.CallOriginal);
   var fakeObj2 = Isolate.Fake.Instance<MyClass>(Members.CallOriginal);
   var fakeObj3 = Isolate.Fake.Instance<MyClass>(Members.CallOriginal);
   var fakeObj4 = Isolate.Fake.Instance<MyClass>(Members.CallOriginal);
   var fakeObj5 = Isolate.Fake.Instance<MyClass>(Members.CallOriginal);
   
   Isolate.WhenCalled(() => fakeObj3.Get(null)).WillReturn(new MyClass.TestBar("phake"));
   Isolate.WhenCalled(() => fakeObj3.Check(null)).WillReturn(false);
   
   Isolate.Swap.NextInstance<MyClass>().With(fakeObj1);
   Isolate.Swap.NextInstance<MyClass>().With(fakeObj2);
   Isolate.Swap.NextInstance<MyClass>().With(fakeObj3);
   Isolate.Swap.NextInstance<MyClass>().With(fakeObj4);
   Isolate.Swap.NextInstance<MyClass>().With(fakeObj5);

   var t = new MyClass();
   var r = t.DoUsefulThing("symbols1", "symbols2", "symbols3", "symbols4", "symbols5");
   Assert.AreEqual(r, new MyClass.Result("something very bad"));
}


Am I right?
answered by tinynick (1.2k points)
0 votes
Yes - The test seems to be right and should give you the desired behavior.
answered by dhelper (11.9k points)
0 votes
dhelper,

Indeed, it works like a charm. My mistake was to solve this problem with use only Natural mocks. Probably with them also possible, but with AAA api it is really easy.

Thank you very much!
answered by tinynick (1.2k points)
...