Digital Me

Random contributions to digital noise
I needed some custom argument matching in my mocks today. I am using JSMock for JavaScript mocking and I find it a bit limited when it comes to argument matching. It mostly satisfies my needs but occasionally I need it to be a bit more flexible, generally speaking. Now, what I introduced is not something that xMock frameworks usually have but JavaScript is a dynamic language and some things are simply different compared to "static" languages (OK, I admit, I've used only NMock so far, but I can't be much wrong here).

To use JSMock you need only jsmock.js. The only change required in the original code is in __delegateMatching method of the ArgumentMatcher, changes are marked red:




__delegateMatching: function(expected, actual) {
if( expected == null ) {
return this.__match( expected, actual );
}
else if( expected.constructor == TypeOf ) {
return this.__match(expected.type, actual.constructor);
}
else if( expected.constructor == Array ) {
return this.__matchArrays(expected, actual);
}
else if( expected.constructor == CustomMatch){
if(!expected.match){
throw new Error("Custom matcher not available");
}
return expected.match(expected.object, actual);
}
else {
return this.__match(expected, actual);
}
}


So that was just one added if clause. All I am saying there is if the expected argument is of CustomMatch then use its custom matcher method instead of original matching logic. There is of course the implementation of CustomMatch that is required:




function CustomMatch(object){
this.object = object;
this.Using = function(customMatcher){
if(typeof(customMatcher) != 'function'){
throw new Error("Can only take constructors");
}
this.match = customMatcher;
return this;
}
}

CustomMatch.Match = function(object){
return new CustomMatch(object);
}


Usage is simple, as one of the expected arguments use something like the following construct:
CustomMatch.Match(expectedObject).Using(customMatchFunction)
Where expectedObject is obviously object that you want to match to the actual argument and the customMatchFunction is the function to use for custom matching, it expects two arguments and returns boolean. So usage might look something like this:


var expectedObject = { fieldOne : 1, fieldTwo : 2 };
var customMatchFunction(expected, actual){
return expected.fieldOne == actual.fieldOne && expected.fieldTwo == actual.fieldTwo;
};

someMock.expects().someMethod(CustomMatch.Match(expectedObject).Using(customMatchFunction));

In your custom matching function you can basically do whatever you want, you could use closure and ignore expected object, or extend the CustomMatch to support something like this: CustomMatch.Use(function(actual){ return actual.fieldOne == 1 && actual.fieldTwo == 2;});

If you are using object literals or duck typing this kind of mock functionality might come handy.
That is something you don't have in C# or Java, C# 3.0 comes closest to object literals with anonymous types but they are by far of less usability, and they have nothing close to duck typing.
I hope you find this small extension justified and, more importantly, useful.

Comments

New comment

required, won't be displayed

optional

Don't type anything here unless you're an evil robot:


And especially don't type anything here:

Basic XHTML (including links) is allowed, just don't try anything fishy. Your comment will be auto-formatted unless you use your own <p> tags for formatting. You're also welcome to use Textile.

Copyright © 2012 Mihailo Lalevic. All rights reserved.
Powered by Thoth.