RSS
Facebook
Twitter

Saturday, November 27, 2010

How to: Invoke events inside your production code using Typemock Isolator

 Using Isolate.Invoke.Event enable event driven unit testing by invoking events on fake or “real” object. If you use events to communicate between parts of your application – it’s a feature you need to know and use. In the last couple of months I have been using it a lot but there is one wall I keep on hitting – when I use Isolate.Swap to fake an instance inside my production code it’s impossible to invoke events on it – because I cannot “touch” the actual faked instance – or is it?
But first things first – let’s talk about invoking events using Typemock Isolator…

Invoking events using Isolator

Let’s say I have a special kind of calculator that due strange consequences known only to the product manager need to work via events. The calculator shell “listen” for events from an “input provider”.
image
Presented with the code below – how can you test it?
public class EventCalculator {
   public int Sum { get; private set; }

   public void RegisterInputProvider(IInputProvider provider) {
      provider.AddTwoIntegers += OnAddTwoIntegerRequested;
   }

   private void OnAddTwoIntegerRequested(object sender, AddTwoIntegersEventArgs e) {
      Sum = e.FirstNumber + e.SecondNumber;
   }
}
One way to test the code is to use Isolate.Invoke (I bet you didn’t see this one coming):
[TestMethod, Isolated]
public void AddTwoIntegers_InvokeEventWithTwoNumbers_SumEqualsSumOfNumbers() {
   var fakeIInputProvider = Isolate.Fake.Instance<IInputProvider>();

   var calculator = new EventCalculator();
   calculator.RegisterInputProvider(fakeIInputProvider);

   var eventArgs = new AddTwoIntegersEventArgs(2, 3);

   Isolate.Invoke.Event(() =>
      fakeIInputProvider.AddTwoIntegers += null, fakeIInputProvider, eventArgs);

   Assert.AreEqual(5, calculator.Sum);
}
For those of you that see event invocation for the first time it might be a little confusing. Isolator use a trick to record the event namely putting the event’s add handler call (the “+=”) inside a lambda. The other two parameters are the events parameters - “this” and “eventArgs”.
Invoking event is a simple as long as you can reach the instance that holds the event – which is not the case if you use Isolate.Swap

Invoking events on future instances

What happens if we need to invoke event on an instance that is created deep inside the production code? at work we use timers and need to test behavior dependent on timer elapsed event – just like in the next class:
public class TimerCounter {
   private readonly Timer _timer;

   public int Count { get; private set; }

   public TimerCounter() {
      _timer = new Timer(1000);
      _timer.Elapsed += OnTimerElapsed;
   }

   public void StartCounting() {
      _timer.Enabled = true;
   }

   private void OnTimerElapsed(object sender, ElapsedEventArgs e) {
      ++Count;
   }
}
It’s not the a very sophisticated class – but it was created to make a point, a timer is created and each time it invokes an event something happens – for simplicity sake I choose to increase a counter.
Testing it should be easy – we have Isolate.Swap and we know how to invoke events, so it shouldn’t be hard to come up with the following test:
[TestMethod, Isolated]
public void TimerElapsed_TimerElapsedCalledTwice_CounterEqualsTwo() {

   var fakeTimer = Isolate.Fake.Instance<Timer>();
   Isolate.Swap.NextInstance<Timer>().With(fakeTimer);

   var timerCounter = new TimerCounter();
   var fakeEventArgs = Isolate.Fake.Instance<ElapsedEventArgs>();

   Isolate.Invoke.Event(() => fakeTimer.Elapsed += null, fakeTimer, fakeEventArgs);
   Isolate.Invoke.Event(() => fakeTimer.Elapsed += null, fakeTimer, fakeEventArgs);

   Assert.AreEqual(2, timerCounter.Count);
}
The test above is simple, elegant and very wrong – it would fail each time you run it claiming that the counter is still ‘0’. So what went wrong? Swap doesn’t actually swap the next instance, it swap it’s behavior instead – meaning that when we call invoke on the fake object it doesn’t invoke event on the object inside our class. I know the good people of Typemock would add this cool feature someday but until then we have a problem – in order to invoke events we need to be able to “touch” the instance in the test.

The solution – reflection

Gur Kashi has come up with a simple solution to this issue – why not use reflection to get the field and use it to invoke the event – the cool thing about Isolator is that it can invoke events on “real” objects as well not just fakes.
With the aid of the following utility method – the class has become testable:
public static T GetField<T>(this object instance, string fieldName) {

   var fieldInfo = instance.GetType().GetField(
                                  fieldName,
                                  BindingFlags.Instance | BindingFlags.NonPublic);

   if(fieldInfo == null) {
      throw new ArgumentException("field not found");
   }

   return (T)fieldInfo.GetValue(instance);
}
And now in the test we can drop the fake instance and just call invoke
[TestMethod, Isolated]
public void TimerElapsed_TimerElapsedCalledTwice_CounterEqualsTwo1() {

   var timerCounter = new TimerCounter();

   var realTimer = timerCounter.GetField<Timer>("_timer");

   var fakeEventArgs = Isolate.Fake.Instance<ElapsedEventArgs>();

   Isolate.Invoke.Event(() => realTimer.Elapsed += null, realTimer, fakeEventArgs);
   Isolate.Invoke.Event(() => realTimer.Elapsed += null, realTimer, fakeEventArgs);

   Assert.AreEqual(2, timerCounter.Count);
}

That’s it. The only downside of this solution is that it’s string based and the test might break if the field name is changed – so make sure you have a good error message if the fields was not found.

Happy coding…


Thursday, November 25, 2010

Rapid Dev – a new unit testing tool is born

It’s no secret that the .NET community has a lot to learn as far as unit testing is concerned. One of the contributing factors to unit testing adaptation is tool support – it’s not secret that if developers can crate and run tests easily form the comfort of their development environment (i.e. Visual Studio). But why settle for the bare minimum? wouldn’t you like your tests to run “automatically” each time you change your code?

This is why Rapid-Dev has been created – it’s a Visual Studio Add-in that monitors your solution and makes sure that each time you change part of your code the relevant unit tests are executed to make sure that you haven’t broken anything.

The tool is has reached a stage were we wanted to share it in order to get feedback and suggestions from actual users.

Rapid-dev

Rapid-dev-closeup

 

More information about the tool can be found at:



Wednesday, November 10, 2010

Discovering race conditions using PostSharp

Since the beginning of computer programming one of the problem that always baffled software developers was how to make sure that their code would run properly once threading has been introduce to the application. I’ve been experimenting with PostSharp for a couple of weeks and I thought that perhaps I can use it to discover multi threading issues in my code.

But first - Can you spot the problem with the following class:

public class UniqueIdFactory 
{
    private int counter = 0;

    public int GetNext() 
    {
        var result = counter++;

        return result;
    }
}

Calling GetNext at the same time there is a chance that both thread would receive the same result. Fixing this issue is simple – just add Lock around counter++ or better yet use the Interlocked class. Obviously this is a simple easy to understand and debug example – in a real world project you just can’t go around adding lock to every place you happen change a variable’s value.

What I came up with is a simple attribute that checks that a specific method or methods are not running on multiple threads at the same time.

[Serializable]
public class SingleThreaded : OnMethodBoundaryAspect 
{
    private readonly object _syncObject = new object();
    private int? _executingThreadsId;
    private int _timesCalled;

    public override void OnEntry(MethodExecutionArgs args) 
    {
        var currThreadId = Thread.CurrentThread.ManagedThreadId;
        lock(_syncObject)
        {
            if(_executingThreadsId != null)
            {
                if(_executingThreadsId != currThreadId)
                {
                    var errorMessage = string.Format(
                                                 "Two threads at the same time {0} and {1}", _executingThreadsId, currThreadId);

                    throw new ApplicationException(errorMessage);
                 }

                 _timesCalled++;

            } 
            else
            {
                _executingThreadsId = currThreadId;
                _timesCalled = 1;
            }
        }
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        var currThreadId = Thread.CurrentThread.ManagedThreadId;
        lock(_syncObject)
        {
            if(_executingThreadsId != currThreadId)
                return; // I'm paraniod - so sue me :)

            _timesCalled--;

            if(_timesCalled == 0)
            {
                _executingThreadsId = null;
            }
       }
    }
}

The attribute is simple - Every time a method is called (i.e. OnEntry)

  1. Check if the method is currently running thread (line 10)
  2. Check if it’s a and if it’s not the same thread as the current thread throw exception (line 11 - 15).

And the rest of the code is just plumbing.

To make this attribute even better you can add the following to the attribute class:

[Serializable]
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple =  true, Inherited = false)]
[MulticastAttributeUsage(MulticastTargets.Method, AllowMultiple = true)]
public class SingleThreaded : OnMethodBoundaryAspect 
{
// code goes here

Now the attribute can be applied to the whole class:

public class UniqueIdFactory 
{
    private int counter = 0;

    [SingleThreaded]
    public int GetNext() 
    {
        var result =  counter++;      

        return result;
    }
}

Although this attribute won’t deterministically catch race conditions – when a race condition will happen in your code – you’ll know about it.

 

Happy coding…



Wednesday, November 03, 2010

Book review: DSLs in Action

After reading DSLs in BOO I wanted to learn more about Domain Specific languages and DSLs in Action looked like a good fit – I wasn’t disappointed…

DSLs comes in many forms and flavors, most books divide them to to distinct groups – internal DSLs and External DSLs.image

  • Internal DSL is a language inside language, using the infrastructure of an existing language to create your syntax.
  • External DSLs  - think back to your compiler course. This refers to creating a new language from the ground up.

This book does an excellent job of showing how DSLs (internal and external) can be created at used in a real world scenario. The book isn’t about a single language either – right after a short introduction (chapters 1 – 3) the book dives into internal DSL creation using Ruby, Groovy, Clojure (chapters 4-6) and Scala (chapter 7) following by a chapter on external DSL creation using ANTLR.

The internal DSL part of the book is all about meta programming on top of the JVM along with ways to integrate the new language with main program written in Java. That’s right most of the book is about Java related languages and technologies. The knowledge can still be applied to other framework (.NET anyone?) but I feel that some hint regarding the Java orientation of this book was in order. My second (and last) beef with this book is its choice of domain: I understand the need to choose an actual real world example that the reader can relate to and understand and in this case trading system as the domain of choice – the whole buying and selling of stocks and what-not is explained in great details in order to help the reader understand the challenges of creating such a system – I found it a bit too much for my taste.

But these are very small issues compared to what I did manage to learn from this book. I was truly amazed that the author didn’t take the easy way out and dedicated a whole chapter to external DSL along with good solid examples and tools that can be used.

Because it’s easy to get lost in all of the information each chapter has a “roadmap” at its beginning that helps understanding what is the chapter is all about:

image

So if you’re interested in domain specific languages and meta programming you want to give this book a try – it’s well worth your time and effort.



Related Posts Plugin for WordPress, Blogger...