Showing posts with label Advanced. Show all posts
Showing posts with label Advanced. Show all posts

Wednesday, July 16, 2008

Mocking asynchronous actions with Typemock Isolator

Here is an answer to a question that keeps popping up every once in a while: how do you stub out asynchronous actions in your class under test? Assuming that you can't\won't change the code and refactor it (usual case in most legacy systems), here is a class with an async action you'd like to stub:

 public class ClassWithAsync

    {

        public void Do(int input,Action<int> resultCallback)

        {

            ThreadPool.QueueUserWorkItem(state =>

                                            {

                                                Thread.Sleep(1000*3);

                                                resultCallback(input*2);

                                            });

        }

    }

 

The ThreadPool.QueueUserWorkItem will invoke our callback asynchronously. Here are two versions of the same test that you can write. The first one is the strogly typed version, which will required the pro or enterprise versions of Typemock Isolator. The second one will work with the free community edition of Typemock.

 

   10 [Test]

   11         public void AsyncMocking_NaturalMocks()

   12         {

   13             bool wasCalled = false;

   14             int passedResult = 0;

   15 

   16             ClassWithAsync target = RecorderManager.CreateMockedObject<ClassWithAsync>();

   17 

   18             using (RecordExpectations rec = new RecordExpectations())

   19             {

   20                 target.Do(0,null);

   21                 rec.Return(new DynamicReturnValue(delegate(object[] parameters, object context)

   22                                                       {

   23                                                           Action<int> theUserCallback =

   24                                                               parameters[1] as Action<int>;

   25                                                           theUserCallback(11);

   26                                                           return null;

   27 

   28                                                       }));

   29             }

   30 

   31             target.Do(5, delegate(int result)

   32             {

   33                 passedResult = result;

   34                 wasCalled = true;

   35             });

   36             Assert.IsTrue(wasCalled);

   37             Assert.AreEqual(11, passedResult);

   38 

   39         }

The way this test works:

in line 16: we create a mocked version of the class we'd like to stub out. then we start a recording session with Isolator where all method calls are recorded. in line 20 we invoke the method for recording purposes. essentially saying "a call to target.do()" will be made later.  any parameters we pass in that line are ignored.

rec.Return tells the recorder what to return or execute when the method is actually called. in this case we are create something called a DynamicReturnValue which allows us to send in our own delegate that does whatever we want. in this case we are taking in the parameters that were sent to this method (the second one is the user's delegate).

when the recording block has ended (the end of the using block) we simply invoke the class. this is code that will usually not be in a test, but will be in the production code that we invoke. we are just simulating what the production code might do. we pass in our own delegate as the callback to the method, and in it we just set some variables that we will assert against.  (We pass in 11 to show that we control the output. the original class would have returned 10.

Here is the community edition version of this test: no record\replay support but should work just the same:

 

   13 [Test]

   14         public void AsyncMocking_ReflectiveMocks()

   15         {

   16             bool wasCalled = false;

   17             int passedResult = 0;

   18 

   19             MockObject<ClassWithAsync> mockObject = MockManager.MockObject<ClassWithAsync>();

   20             mockObject.ExpectAndReturn("Do",

                                         new DynamicReturnValue(delegate(object[] parameters, object context)

   21                                                     {

   22                                                      Action<int> theUserCallback =

   23                                                      parameters[1] as Action<int>;

   24                                                      theUserCallback(((int)parameters[0]) *2 +1);

   25                                                      return null;

   26 

   27                                                     }));

   28 

   29             ClassWithAsync mockedClass = mockObject.MockedInstance;

   30             mockedClass.Do(5, delegate(int result)

   31                                   {

   32                                       passedResult = result;

   33                                       wasCalled = true;

   34                                   });

   35             Assert.IsTrue(wasCalled);

   36             Assert.AreEqual(11,passedResult);

   37 

   38         }

 

Any questions?

Tuesday, July 15, 2008

Configuration via Typemock Interception

A while ago Udi Dahan wrote that he'd like a way to configure objects by just setting property values on an object. those "setters" will be intercepted and saved to a some config object (or container) for the future use of the application.

Udi turned to me a while ago and asked if perhaps typemock could be used to do this. an unusual scenario for a mocking framework, but a valid one for an AOP framework (which typemock is sort of)

It lost my mind after a while but today I talked with udi again, and came up with a simple solution to his problem. Here is a simple class that can be used like this:

 

        [Test]

        public void HandleCallsOn_OnlyFirstInstanceGetsIntercepted()

        {

            List<object> args = new List<object>();

            MyClass configure =

                TypeHandler.HandlePropertyCallsOn<MyClass>(

                     delegate(Type type, string propertyName, object passedValue)

                              {

                                 args.Add(passedValue);

                              });

 

            configure.ConnectionString = "a";

            configure.SomeNumber = 3;

            new MyClass().ConnectionString = "b";

            Assert.AreEqual(2,args.Count);

 

        }

Calling "HandlePropertyCallsOn" and giving a callback allows you to do whatever you want when the properties are set (the real properties are never really set). The BIG plus is that the properties do not have to virtual for this to work.

 

here is the code of the class that does this. you can use this with the free Community Edition of Typemock Isolator by just adding a reference to it in your project.

 

Just copy this class into your project to use it.

 public class TypeHandler

    {

        public static TFrom HandlePropertyCallsOn<TFrom>(Action<Type, string, object> callback)

        {

            MockObject<TFrom> mock = MockManager.MockObject<TFrom>(Constructor.NotMocked);

            mock.MockMethodCalled+=delegate(object sender, MockMethodCallEventArgs e1)

                                       {

                                           callback(typeof(TFrom), e1.CalledMethodName, e1.SentArguments[0]);

                                       };

 

 

            foreach (PropertyInfo property in typeof(TFrom).GetProperties(BindingFlags.Public|BindingFlags.Instance))

            {

                mock.ExpectSetAlways(property.Name);

            }

            return mock.Object;

        }

    }

 

you can use this class to configure calls on even interfaces without having a real class on them, or on abstract classes and such.

Monday, June 2, 2008

More on Using Marshal.GetExceptionCode()

A long time ago Ayende pointed out that GetExcpetionCode can be used to know whether an exception was thrown from inside a finally clause. We have found this technique also useful (thank you Ayende) from inside a Dispose method.

However, we also needed to know the exception type that was thrown and this apparently is not easily done. Up until now we have not found a "proper" mechanism, so we had to revert to some messy workaround. This works for us, only due to the fact that the only interesting exception type we needed to recognize is the NullReferanceException.

here is how to do it:

public class Util
{
static readonly private int _NullReferenceCode;

public static int NullReferenceCode
{
get { return _NullReferenceCode; }
}

static Util()
{
//this will store the code for the NullReferenceExcpetion
try
{
String dum = null;
dum.ToString();
}
catch
{
_NullReferenceCode = Marshal.GetExceptionCode();
}
}
}

and then we can use it as follows:


public void Dispose()
{
if (Marshal.GetExceptionCode() == Util.NullReferenceCode)
{
//do some logic
}
}


Up until now we have not found a good API to translate the code returned to a usable exception object (or any other alternative), which is kind of frustrating since we do know that info is out there (specifically its on the IL stack) and we also know that it can be accessed using the $exception in the quick watch window (BTW the $exception thing by itself is a very handy trick).




Thursday, April 10, 2008

Argument Checking

One common use of a mocking framework is to check interaction between classes, Specifically checking correct arguments passing between calls.

Like any other framework Typemock Isolator also contain such an ability:

using (RecordExpectations recorder = RecorderManager.StartRecording())
{
MyClass mock = new MyClass();
mock.DoStuff(5);
recorder.CheckArguments();
}

However when doing so its important to note that the verification is done during the actual call time. When later on in the test when someone calls the DoStuff method and passes arguments they are checked immediately and the Isolator will fail the test by throwing an exception on the call.

this approach which is used by most framework can be confusing when happening inside a try-catch block.

for example the following code will not fail as expected:

try
{
MyClass target = new MyClass();
target.DoStuff(4);
}
catch
{
//some error handling code
}

The exception thrown by the Isolator is caught, and in most cases not re-thrown and the test does not see it.

The trick to solve such an issue is to defer the argument checking to the final verification stage (the call to MockManager.Verify) by doing:


MockManager.ValidateArgsOnVerify = true;

That being said we are working on removing the need for the user to specify this. We hope to incorporate this in our next release.