Julian Jelfs’ Blog

Why FakeItEasy beats Rhino.Mocks

Posted in Unit Testing by julianjelfs on March 30, 2011

We all know that when we’re unit testing we should use mocks and stubs to test our component’s interactions. Like many people I have been using Rhino mocks for a long long time. The introduction of the AAA syntax a while ago has made things considerably easier, but I have still always found that as the complexity of the code under test increases, then the burden on the tests in terms of set up also increases. So too does the likelihood that a supposedly targeted unit test will be broken by some orthogonal code change.

This problem is exacerbated when people don’t understand the difference between mocks and stubs and also when people try to test too many things in a single test. The problem is that when you confuse mocks and stubs you almost inevitably end up testing more than one thing because you end up setting up a whole host of expectations which have little to do with your test just to get the thing to run. This leads to brittle, annoying tests which makes people stop wanting to write them.

The great thing about FakeItEasy is that everything you create is just a Fake and it will behave like a stub or a mock depending on how you interact with it. This makes it much much easier to write a targeted unit test against a complicated piece of code without getting swamped in set up code. It also makes it much less likely that you will use a mock when you need a stub and much less likely that your test will break when something unrelated changes.

If you consider the example of trying to fake interaction with the NHibernate criteria API. Even very simple criteria queries are a pain to mock because of the nature of the API. You might say that this is too low level and that NHibernate should be behind some sort of abstraction interface. Maybe, but the NHibernate criteria API is an abstraction interface and in this case it is precisely the exact calls being made to the API that I want to test.

Let’s say I have the following simple code (assume that the NHibernate session is injected):

   1: public IEnumerable<Thing> GetThings(string filter)
   2: {
   3:     var criteria = _session.CreateCriteria(typeof(Thing));

   4:

   5:     if (!string.IsNullOrEmpty(filter))

   6:         criteria.Add(Restrictions.InsensitiveLike("Property", string.Format("%{0}%", filter)));

   7:

   8:     return criteria.List<Thing>();

   9: }

Let’s say that what I want to test is that when a filter is supplied, the correct restriction is added to the query. With Rhino mocks I might try something like:

   1: [Test]

   2: public void FilterIsApplied()

   3: {

   4:     var criteria = MockRepository.GenerateMock<ICriteria>();

   5:     var session = MockRepository.GenerateStub<ISession>();

   6:     session.Stub(s => s.CreateCriteria(typeof (Thing)))

   7:         .Repeat.Once().Return(criteria);

   8:

   9:     criteria.Expect(c => c.Add(Restrictions.InsensitiveLike("Property", "%filter%"))).Repeat.Once();

  10:

  11:     var controller = new ThingController(session);

  12:

  13:     var result = controller.GetThings("filter");

  14:

  15:     criteria.VerifyAllExpectations();

  16: }

The main problem with this is that it doesn’t work. The reason it doesn’t work is because Restrictions.InsensitiveLike returns a new Criterion i.e. not the same Criterion that we have specified in our expectation and therefore the arguments don’t match. Our only option is to set IgnoreArguments. But in this case, that is the beginning and end of what we want to test, so if we IgnoreArguments we might as well delete the test.

Another problem is that, even if this test did work, it would be brittle. Suppose someone changed the code as follows:

   1: public IEnumerable<Thing> GetThing(string filter)

   2: {

   3:     var criteria = _session.CreateCriteria(typeof(Thing))

   4:         .AddOrder(Order.Desc("Property"));

   5:

   6:     if (!string.IsNullOrEmpty(filter))

   7:         criteria.Add(Restrictions.InsensitiveLike("Property", string.Format("%{0}%", filter)));

   8:

   9:     return criteria.List<Thing>();

  10: }

To add an order by clause. This has nothing to do with our test case, but it would break our test. We can solve both of these problems with FakeItEasy as follows:

   1: [Test]

   2: public void FilterIsApplied()

   3: {

   4:     var session = A.Fake<ISession>();

   5:     var criteria = A.Fake<ICriteria>();

   6:     Any.CallTo(session).WithReturnType<ICriteria>().Returns(criteria);

   7:     Any.CallTo(criteria).WithReturnType<ICriteria>().Returns(criteria);

   8:

   9:     var controller = new ThingController(session);

  10:

  11:     var result = controller.GetThings("filter");

  12:

  13:     A.CallTo(() => criteria.Add(

  14:         A<ICriterion>.That.Matches(c => c.ToString() == Restrictions.InsensitiveLike("Property", "%filter%").ToString()).Argument))

  15:         .MustHaveHappened(Repeated.AtLeast.Once);

  16:

  17: }

Line 7 means that the test does not break when the order by criteria is added – it shouldn’t and doesn’t care about it. But the really nice thing is the way we express our expectation. We do not have to resort to IgnoreArguments (though there is an analogous option if you need it) because we have the ability to supply a predicate to determine whether each individual argument matches our expectations. We can also choose to ignore individual arguments which will further reduce the probability of the test breaking for the wrong reasons. So what we are left with is an easy to write, targeted resilient unit test.

PS – don’t get too hung up on whether or not this is a test you should be writing. It’s just a test that demonstrates nicely why I think FakeItEasy is better than Rhino mocks.

Tagged with:

jQuery keyboard control plug-in

Posted in Javascript, jQuery by julianjelfs on September 11, 2010

I had a requirement to come up with some keyboard control mechanism for our web app which I would like to be able to handle some peculiar requirements. Most tricky is that we do not know what the labels are in advance because they are configurable by the user. In the past this has led to a lot of duplicate access keys because we derive them on the fly.

I though maybe we could use something along the lines of the google chrome mouseless browsing extension which creates a little floating div with a number in it for each “clickable” thing. So I created a simple jQuery plug-in which does just that:

   1: (function($){

   2:  

   3: $.fn.keyboard = function(selector){

   4:     if(!selector || selector.length == 0)

   5:         return this;

   6:     

   7:     var shortcutsShowing = false;

   8:     var timer = null;

   9:     function hideShortcuts(){

  10:         $("div.kb-shortcut").remove();

  11:         target.unbind("keydown.kb");

  12:         target.unbind("keydown", "esc");

  13:         shortcutsShowing = false;

  14:         if(timer){

  15:             clearTimeout(timer);

  16:         }

  17:     }

  18:  

  19:     target.bind("keyup", "alt", function(){

  20:         if(!shortcutsShowing){

  21:             shortcutsShowing = true;

  22:             var kb =  $(selector, target);

  23:             var targets = {};

  24:             kb.each(function(i){

  25:                 targets[i] = $(this);

  26:                 var pos = $(this).offset();

  27:                 $("<div class='kb-shortcut'>" + i + "</div>")

  28:                     .appendTo("body")

  29:                     .css({

  30:                         top : pos.top + 5,

  31:                         left : pos.left + 5,

  32:                         opacity : 0.8

  33:                     });

  34:             });

  35:  

  36:             var buffer = [];

  37:             var timer = null;

  38:             target.bind("keydown.kb", function(e){

  39:                 if(timer){

  40:                     clearTimeout(timer);

  41:                     timer = null;

  42:                 }

  43:  

  44:                 buffer.push(String.fromCharCode(e.which));

  45:  

  46:                 timer = setTimeout(function(){

  47:                     var key = buffer.join("");

  48:                     buffer = [];

  49:                     var target = targets[key];

  50:                     if(target != null){

  51:                         $("div.tree").blur();

  52:                         target.click()

  53:                         hideShortcuts();

  54:                     }

  55:                 }, 500);

  56:             }).bind("keydown", "esc", function(){

  57:                 hideShortcuts();

  58:             }).one("click", function(){

  59:                 hideShortcuts();

  60:             });

  61:         } else {

  62:             hideShortcuts();

  63:         }

  64:     });

  65:     

  66:     return this;

  67: };

  68: })(jQuery);

So basically you call it on the container that you want to provide the scope for the event capture e.g. $(“body”) and you pass it a selector which will identify all the elements which you want it to highlight. So if you want it to highlight buttons you’d do this:

   1: $("body").keyboard(":button");

Having done that, when the user hits the alt key, all buttons will be marked with a little square with a number in it. The user types the number they want and that element gets clicked. Simple. It will also work with numbers of more than one digit, because the key presses are recorded in a buffer and then joined together after a brief pause (the duration of which could easily be made configurable). It has the advantage of being very easy to drop into an existing page without really having to rewrite anything. Don’t know whether we’ll use it – everyone might hate it, but I quite like it.

The little highlight squares have the class “kb-shortcut” attached to them, so you can style them how you like (again that could easily be passed in as an option).

One thing to note, this is currently dependent on the jquery.hotkeys plugin to capture the alt and escape key presses. This could easily be refactored to just use standard jquery functionality only.

Who’d have thought it

Posted in Uncategorized by julianjelfs on July 16, 2010

Flock is actually pretty cool

jQuery plug-in for deferred resize (or anything)

Posted in Javascript, jQuery by julianjelfs on May 7, 2010

There are a class of UI events that fire many many times in quick succession. Things like mouse move, resize or even keyup. Often (in my experience) you might want to perform some action after the event has stopped happening rather than for each and every event. Suppose you want to do some expensive re-organisation of the UI in response to the resizing of some container element then you most likely don’t want to do this in response to every resize event, rather you want to wait until it appears that the user has stopped resizing and then perform the action. I have found it useful to encapsulate this pattern as a jQuery plug-in so that instead of this:

element.resize(function(){
    //do something expensive
});

I can do this:

element.deferredResize(function(){
    //do something expensive
}, 300);

And the plug-in looks like this:

$.fn.extend({    
    deferredResize : function(fn, delay){
        var timer = null;
        $(this).resize(function(){
            if(timer != null){
                clearTimeout(timer);
                timer = null;
            }
            timer = setTimeout(fn, delay);
        });
        return this;
    }
});

So when it picks up a resize event it will wait 300 milliseconds before kicking of the handler. In the interim, if it receives another resize event it will cancel the first timer and start the wait again. The end result is that you can achieve a nice balance between performance and responsiveness.

You could refactor this as a general extension to $.bind I guess but I think it is less useful for other events.

Scope shenanigans part three

Posted in Javascript by julianjelfs on January 24, 2010

So in my previous posts here and here I described a problem I was having with Microsoft Ajax script library serialisation of Dates that had been created in a different scope to that where the serialisation is actually taking place. I also described a somewhat hacky solution that involves iterating through the data to be serialised, tagging dates and then switching scope and recreating the dates in the new scope.

This works fine, but I don’t like the idea of having to recreate all these dates all the time so I go to thinking a bit more about what (someDate instanceof Date) actually means. Roughly it means, was this date created with the Date function. Given that I wandered if the following two statements were equivalent:

var date = new Date();
alert(date instanceof Date);    //true
alert(date.constructor === Date);    //true

If so then perhaps I can do the following:

var dateA = top.frames["frameB"].date;
alert(dateA instanceof Date);    //false
dateA.constructor = Date;    //change the constructor function
alert(dateA instanceof Date);    //true

If so, I can avoid having to recreate the Date objects, I can just reassign their constructor functions. Sadly, it doesn’t work. It seems that there is more to instanceof than just checking the constructor function. So we still have to be wary of using instanceof, but remember that the original problem was with the Microsoft Ajax script serialisation so all is not lost. The MS code detects type like this:

Type.prototype.isInstanceOfType = function Type$isInstanceOfType(instance) {    
    var e = Function._validateParams(arguments, [{name: "instance", mayBeNull: true}]);    
    if (e) throw e;    
    if (typeof(instance) === "undefined" || instance === null) return false;    
    if (instance instanceof this) return true;    
    var instanceType = Object.getType(instance);    
    return !!(instanceType === this) ||           
        (instanceType.inheritsFrom && instanceType.inheritsFrom(this)) ||           
        (instanceType.implementsInterface && instanceType.implementsInterface(this));
}

So it uses instanceof first, but if that returns false, it goes on to call Object.getType which looks like this:

Object.getType = function Object$getType(instance) {    
    var e = Function._validateParams(arguments, [{name: "instance"}]);    
    if (e) throw e;    
    var ctor = instance.constructor;    
    if (!ctor || (typeof(ctor) !== "function") || !ctor.__typeName || (ctor.__typeName === 'Object')) {        
        return Object;    
    }    
    return ctor;
}

Which is basically just returning the object’s constructor property. So by overwriting the constructor argument as described, although instanceof still cannot be trusted, Date.isInstanceOfType(object) as defined in the Microsoft Ajax script library will work as expected and therefore so will MS javascript serialisation.

The upshot is that by overwriting the date object’s constructor property with the Date function from the required scope we can get Date.isInstanceOfType(object) to return true and there is no need to completely recreate the date in the required scope. If, however, you want instanceof to work – the only way I can achieve that is to recreate the date. If anyone knows of a better way, I’d love to hear it.

Solution to the cross-frame instanceof scope problem

Posted in Javascript by julianjelfs on January 15, 2010

In my previous post I explained how I ran into the problem that dateB defined on frameB would return false if you execute dateB instanceof Date in frameA. I thought that this was because the data somehow got mangled when marshalled from one window to another. In fact it is nothing to do with that. The instanceof function is working entirely correctly, it’s just maybe not doing what you expect.

When you write (dateB instanceof Date) you are really asking was dateB created with function Date. Now when you add the implicit scope you begin to see why it doesn’t work the way you want. dateB was created in frameB with the function frameB.Date. So when you say dateB instanceOf frameA.Date as you implicitly are when you run this code in frameA, then of course it should and does return false.

If you explicitly call dateB instanceof frameB.Date it still returns true.

If you bear this in mind when calling functions that return data on other frames you can get round it. One approach which I have taken is shown here:

var frameB = top.frames["frameB"];

var dateB = crossFrame(frameB, frameB.getMeADate);

alert(dateB instanceof Date);     //give true

function crossFrame(target, func, parms){
    var result = func.apply(target, parms);
    result = tagDates.call(target, result);
    tagDates.call(target, parms);
    fixDates(parms);
    return fixDates(result);
}
function fixDates(val){
    if (val == null) return val;
    if (val["_date"]!==undefined) {        
        return new Date(val);
    }
    if (typeof (val) != 'object') return val;
    if (val instanceof Array) {
        for (var j = 0,len=val.length; j < len; j++) {
            val[j] = fixDates(val[j]);
        };
        return val;
    }
    for (var prop in val)
        val[prop] = fixDates(val[prop]);
    return val;
}

function tagDates(val){
    if (val instanceof Date) {
        val._date = true;
        return val;
    }
    if (typeof (val) != 'object') return val;
    if (val == null) return val;
    if (val instanceof Array) {
        for (var j = 0,len=val.length; j < len; j++) {
            val[j] = tagDates(val[j]);
        };
        return val;
    }
    for (var prop in val)
        val[prop] = tagDates(val[prop]);
    return val;
}

So we pass the target frame and the target function and the arguments array to the function crossFrame. Inside crossFrame we call the function on the target frame and get the results. At this point we are in calling frame scope. We then call tagDates using the target frame as scope. In this scope we can correctly identify the dates in the data. For each one we find, add an attribute so that we can identify it as a date later.

Then back in the calling scope we call fixDates which looks for the objects we tagged as dates and overwrites them with an equivalent Date created in the calling scope.

This means that when the data is returned from the call to crossFrame, any dates will have been re-created in the calling scope and any call to instanceof will work as expected.

The code above is not complete because it only handles dates. That’s all I have a problem with so it works for me but it could easily be extended for any other type because the underlying problem is not about types it is about scope.

Cross-frame dates cannot be serialised by Sys.Serialization.JavaScriptSerializer

Posted in Javascript by julianjelfs on January 15, 2010

Lets say you have a page with two iframes on it (frame A and frame B). In frame A we do this (forget why):

window.testDate = new Date();

and then in frame B we do this:

Sys.Serialization.JavaScriptSerializer.serialize(top.frames["frameA"].testDate);

We will get a stack overflow (in IE7 at least) when using the debug version of the Microsoft Ajax framework and we’ll just get nothing with the release version.

The root cause seems to be that in frame A testDate instanceof Date is true. But if we reference it from frame B it is false. This means that the serialiser does not correctly identify it as a date etc etc.

This is annoying if you are using the serialiser directly, but it is really annoying if you are forced to use it because you are using an MS Ajax script service proxy. I guess I will have to use jQuery to call the script service directly and take charge of serialisation myself using some other JSON library. I have seen it done but I just know it’s going to be painful…

PS – this issue is nicely described here

Cross-domain automatic iframe resizing

Posted in Uncategorized by julianjelfs on December 3, 2009

As we all know there are security restrictions when script from domain A tries manipulate content from domain B. This causes a lot of inconvenience. One example is automatic iframe resizing. It sounds simple on the face of it. When your iframe content loads you just need to tell the parent window what the content size is and then it can resize the iframe for you. The problem is that if the iframe content does not come from the same domain as the main page, you cannot do this. At least you cannot do this in the way you expect to.

This is a fairly well documented problem and the most common solution is to use the url fragment identifier hack. Basically this hack exploits the fact that any window or frame can set the location of any other window or frame (although perhaps counter intuitively it cannot read the location of a window from a different domain).

This trick can be used to accomplish cross-domain iframe resizing. Having googled this subject I found a good post on how to do this here. While the code in that post works well, I think it is quite verbose and in the end I reduced it to the following:

For each frame on the page, set the hash fragment of the frame’s src attribute to be the frame’s id:

<iframe id="myFrame"
    scrolling="no"
    frameborder="0"
    width="100%"
    src="whatever.aspx?name=val#myFrame">
</iframe>

In the main page add the following script to execute when the page starts up (I’m using jQuery here but you don’t have to):

window.setInterval(function(){
    var hash = window.location.hash.replace("#","");
    if(hash.length == 0)
        return;

    var pair = hash.split("=");
    $("#"+pair[0]).animate({height:pair[1]});
    window.location.hash = "";
}, 100);
and in each content page being loaded add the follow script to execute when the page starts up:
window.setInterval(function(){
    if(top == self)
        return;

    var bh = $("body").height();
    var wh = $(window).height();

    if  (Math.abs(bh - wh) > 10){
        var hash = self.location.hash.replace("#","");
        if(hash.length == 0)
            return;
        top.location.hash = hash + "=" + (bh + 10);
    }
}, 100);

What’s happening? Each content window is running a loop which detects if its window is either too big or too small and if it is, it writes a name value pair containing the id of the frame and the required height e.g. frameId=500 to the hash fragment of the main window’s url. It gets the frameId from its own hash fragment. This is allowed because we are simply writing to the hash, not trying to read. It will not cause a reload because we are only updating the hash fragment.

Meanwhile the main page is running a loop to monitor its own hash fragment looking for modifications made by the frames. When it finds a name value pair in its hash fragment it simply finds the corresponding frame and sets its height (animation an optional extra).

Obviously you can set the interval on the loops to whatever is appropriate.

ClientScriptManager.GetWebResourceUrl type parameter

Posted in Uncategorized by julianjelfs on November 22, 2009

So this method returns a URL reference to a resource embedded in an assembly. No problem with that – useful. The thing that annoys me about this is the first parameter. It is a parameter of type “Type” and according to the documentation describes the type of the resource. This is obviously nonsense. If I am embedding a javascript file in an assembly what type is that? typeof(javascript file) ? In the remarks section on the documentation we get a bit more information:

“You specify the type based on the object that will be accessing the resource”

Which seems again to be meaningless. What does this mean for a script file? It turns out that the only thing you have to make sure of really is that the type you specify belongs to the same assembly that the resource is embedded in otherwise it will not work. This is the one important point that the documentation does not clearly tell you.

Command-Q without all the other crap

Posted in Uncategorized by julianjelfs on September 18, 2009

Background – I have an iMac, I’ve had it for about a year. Love the shiny hardware, hate the software. The beautiful thing is that all the evangelising in the world cannot make me wrong about this – I HATE MY MAC.

So I reduced the size of my OS X partition to the minimum and installed Windows  7 on it and the relief is enormous.

The one thing I missed was the Command-Q shortcut to close the active window (yes honestly this is the only thing I missed). In windows the shortcut is an irritatingly wrist twisting Alt-F4.

Then I found autohotkey which is a very nice open source tool for scripting hotkeys (and it seems a lot more besides).

All I have to do is drop a script like this:

#q::Send !{F4}

into my start up folder and I have all of the benefits of Mac OS with none of the tedious smug cruft.