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
0 votes
I'm having troubles testing in this situation:

public class A
{
private Dictionary<Type> _someInterfaces;

public A(){ _someInterfaces = new Dictionary<Type>(); }

public Dictionary<Type> Interfaces { get { return _someInterfaces; } }
}
public class B
{
private static readonly A a = new A();

public static Dictionary<Type> Interfaces { get { return a.Interfaces; } }

public static IInterface GetInterface(Type type) { ... }
}

I can isolate type A from B and test methods works singularly, but when I run all test methods in the test unit, only the first executed test works.

I tried with AAA and Natural Mocks with no success.

How can I test "B class" in isolation?

Regards
asked by eddy2oo8 (680 points)

5 Answers

0 votes
Hi Eddy

generally what you want to so in this case is to fake the creation of class A, set the expectations on the fake object and than swap it with the real object.

There is a limitation of the Isolator which you may encountered in your tries:
We cannot fake mscorlib types like the Dictionary class.
However we can fake mscorlib interfaces.
So i see two possible workarounds in this case:
1. Change the return type of B.Interfaces and A.Interfaces to IDictionary
2. Create a wrapper around Dictionary class.

In the example bellow I assume that the methods returns IDictionary:
[Test]
public void Test()
{
    Dictionary<Type> fakeDictionary = new Dictionary<Type>();
    fakeDictionary.Add(typeof(int), "int");
    fakeDictionary.Add(typeof(B), "B");

    //fake the A class.
    A fakeA = Isolate.Fake.Instance<A>();
    //create expetation for A.Interfaces property and return fake Dictionary.
    Isolate.WhenCalled(()=> fakeA.Interfaces).WillReturnCollectionValuesOf(fakeDictionary);
    //Here we swap the next instance of A with our fakeA object.
    Isolate.Swap.NextInstance<A>().With(fakeA);

    IDictionary<Type> d = B.Interfaces;
    Assert.AreEqual(d[typeof(int)], "int");
    Assert.AreEqual(d[typeof(B)], "B");
}


Additionally if you don't need the Dictionary that is returned from Interfaces property you can create your fake A with default Members.ReturnRecursiveFakes
That will make all methods and properties return faked objects or default values in cases where the Isolator can not create fakes.

A fakeA = Isolate.Fake.Instance<A>(Members.ReturnRecursiveFakes);
// set expectations on fakeA as needed


Hope it helps.
answered by ohad (35.4k points)
0 votes
Ohad,

my sample was a little bit misleading...

My concerns and difficulties are about how to mock future instances of class A inside class B, since A is a static instance inside class B.

I'm partially able to test class B isolating class A, but I'm a bit confused. An example will help...

ParentClass have a static instance of ChildClass

[TestMethod]
[VerifyMocks]
public void Should_access_internal_property() // OK
{
   using (RecordExpectations recorder = RecorderManager.StartRecording())
   {
      recorder.MockAllInstances = true;
      var theChildClass = new ChildClass();
      var expectedCall = theChildClass.SomeProperty;
      recorder.Return(null);
   }

   var call = ParentClass.SomeProperty;
}

[TestMethod]
[VerifyMocks]
public void Should_call_internal_method_when_somemethod_arg_is_not_null() // OK
{
   using (RecordExpectations recorder = RecorderManager.StartRecording())
   {
      recorder.MockAllInstances = true;
      var theChildClass = new ChildClass();
      theChildClass.SomeMethod(null);
      recorder.Return(null)
   }

   ParentClass.SomeMethod(somevalue);
}

[TestMethod]
[VerifyMocks]
public void Should_not_pass_the_test_1() // Test fail, OK 
{
   using (RecordExpectations recorder = RecorderManager.StartRecording())
   {
      recorder.MockAllInstances = true;
      var theChildClass = new ChildClass();   
      recorder.FailWhenCalled(theChildClass.SomeMethod(null));
   }

   ParentClass.SomeMethod(typeof(int)); // Will call the internal method, and test will fail
}

[TestMethod]
[VerifyMocks]
public void Should_not_pass_the_test_2() // Test fail, bug?
{
   try {
   using (RecordExpectations recorder = RecorderManager.StartRecording())
   {
      recorder.MockAllInstances = true;
      var theChildClass = new ChildClass();   
      recorder.FailWhenCalled(theChildClass.SomeMethod(null));
   }

   ParentClass.SomeMethod(typeof(int)); // Will call the internal method, but test will NOT fail
   }
}



First two test's scenario works correctly, third test should fail and it does, fourth test should fail and it doesn't cause it's in try scope.

Second thing, I don't understand how the instance creation of ChildClass inside the recorer scope affects the tests. Shouldn't the instance creation of ChildClass set an expectation on constructor? If it's so, shouldn't all the tests fails but first?

Thanks
answered by eddy2oo8 (680 points)
0 votes
Hi Eddy,

Regarding the issue you are encountering, I'm not sure what you are trying to test. You are catching the exception in the try clause (shouldn't it have a catch/finally?), and because it's not rethrown it gets swallowed and the test passes. How would you expect it to behave otherwise?

Regarding the question about expectations: you are correct in saying that expectations created in a recording block should be verified on, but constructor expectations are handled differently. Verifying a constructor has been called is currently not supported in Isolator (but we intend to add this feature).

Thanks,
Doron
Typemock Support
answered by doron (17.2k points)
0 votes
Doron,

ok for the constructor, now I understand.

The example where I use try/catch clauses are there just because I noticed that when FailXXX and ExpectXXX expectations are always succesfull when the test is in a try catch, and sounded as a strange behaviour.

Thanks.
answered by eddy2oo8 (680 points)
0 votes
Eddy - what happened is that the try clause swallowed the exception so the test as a whole did not fail. What I use when I test exceptions are either the MSTest [ExpectedException(Type)] in conjunction with the following pattern to verify against the exception itself:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void Test()
{
   // set up code
   ...

   try
   {
      target.ShouldThrow();
   }
   catch(NullReferenceException ex)
   {
      // verify on ex.Message, ex.StackTrace or anything else you need
      ...

      throw; // this rethrows the exception and is caught in the [ExpectedException] attribute, making sure the exception was actually thrown
   }
}
answered by doron (17.2k points)
...