Showing posts with label Tips and Tricks. Show all posts
Showing posts with label Tips and Tricks. 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.

Wednesday, July 9, 2008

Musings about Refactoring

For the last couple of weeks I've been paired with Lior on a large refactoring task that was long overdue. We did not have any specific bug to fix, but rather wanted to simplify some of the dustier corners of our codebase. This really helped me realize the importance of refactoring, and specifically of doing it frequently.


The first thing I noticed was that both of us struggled when reading the code; it was not badly written - there were messy parts and elegant parts like anywhere else - it was just alien to us. We did not know what the author meant when writing the code, the naming convention was confusing to us and the reasons behind some of the trickier stuff were a mystery to us.


Now, after major renaming, commenting out, deleting, simplifying and extracting, we believe the code is simpler and more readable. However, I believe that if we leave it at that in a couple of years another pair may be in the exact same situation - our code may be mystifying to them, no matter how self descriptive we tried to make it. By refactoring frequently this can be avoided, or at least minimized.


Refactoring is easy to neglect; in the TDD cycle we never forget to write tests, implement code and test it, but it's easy to leave it at that once all tests passed. I intend to put emphasize on doing another refactor + test run on any code I product, in order to make sure I did my best to keep it simple. Also, when fixing something I fully intend to look beyond the immediate fix (which may be something small like adding an 'if' condition), and go over the entire method/class I modified. You may write code that flows like poetry, but after patching it a couple of times the rhymes will be off and the punch line is gone. This may not seem important when trying to get as many features as possible out the door, but missing it may have severe effect on the quality of the code base, the time it takes new people to learn it and how testable it is.

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).




Friday, May 23, 2008

Running Typemock Isolator Tests using TeamCity Nunit Runner

Wendy just sent me over an email telling me how she was able to use TeamCity's Nunit test runner to run Unit tests that use Typemock. the "problem" was that for typemock to run, it's profiler needs to be active as part of the unit runner process.

here's what she did:

"figured it out – I used the environmental variables setting for the build and set the values from mocking_on:

Cor_Enable_Profiling=0x1

COR_PROFILER={B146457E-9AED-4624-B1E5-968D274416EC}

I’m so clever :P"

Indeed you are! Thanks for the heads up, Wendy.

the Mocking_on she refers to is the mocking_on.bat that comes as part of the Typemock Isolator installation.

Saturday, May 17, 2008

Swapping calls between classes without dependency injection

Eli Lopian, Typemock CEO and awesome Coder, just created a nice little API wrapper around Typemock Isolator that would allow a very simple and readable "Swapping" effect between classes. It would allow you to write code like this:

    [Test]

       public void SwapStatic_CallsFake()

       {

           Swap.StaticCalls<TypeA, TypeB>();

           Assert.AreEqual(2, TypeA.StaticReturnOne());

           Swap.Rollback();

       }

 

       [TestMethod]

       public void SwapInstance_CallsFake()

       {

           Swap.NextNew<OriginalClass, FakeClass>();

           OriginalClass swappedInstance = new OriginalClass();

           Assert.AreEqual(2, swappedInstance.ReturnOne());

       }

 

The first test uses the "Swap" class to replace static calls and redirect them to your own class with static methods. The second one is more advanced and will mock all instance calls made on the next instance that will be created of that type. so the last line on the second test will actually call a method against the FakeClass type.

pretty cool and very readable. download the code and binaries from his post.

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.