Wiki

Clone wiki

mosquito / Home

Mosquito - Painless JavaScript Mocking

"What, not another JavaScript mocking framework!" I hear you scream, but before you press the back button let me explain why you should use Mosquito - It solves problems that are unique to JavaScipt.

What Mosquito does:

  • Mocks methods defined in the constructor as well as the prototype object
  • Provides an elegant DSL
  • After the fact verification
  • Encourages white box testing
  • Removes the need for dependency injection
  • Allows the mocking of object literals

What Mosquito does not do:

  • Excessively pollute the global namespace
  • Modify the prototype of JavaScript base types
  • Use third party JavaScript libraries that may do either of the above

So stop yapping and give us some examples!

In order to get started you will need to include the mosquito_min.js script:

<script type="text/javascript" src="<PATH_TO_SCRIPT>/mosquito_min.js"></script>

Let's start with a constructor which we can play around with:

function MyClass(){
    this.doThis = function(){
        console.log("this");    
    }
}
MyClass.prototype = {
    doThat: function(){
        console.log("that")
    }
};

So what would a simple mock look like?

var myMock = mock(MyClass);
myMock.doThis(); //Returns nothing
myMock.doThat(); //Returns nothing

How about some return values?

when( myMock.doThis() ).thenReturn("love mosquito");
myMock.doThis(); //Returns "love mosquito"

But do you have argument specific return values?

when( myMock.doThat(1) ).thenReturn("You passed one");
myMock.doThat(1); //Returns "You passed one"

Ok, what about some argument type specific return values?

when( myMock.doThis("{any array}") ).thenReturn("You passed some array");
myMock.doThis([1,2,3]); //Returns "You passed some array"

Or maybe a bit of a mix?

when( myMock.doThis("{any object}", "number", "{any number}") ).thenReturn("I hope you agree");
myMock.doThis({"mosquito": "is"}, "number", 1); //Returns "I hope you agree"

Ok cool, so we can stub out our mocks, what about behaviour verification?

myMock.doThis();
verify( myMock.doThis() ).called(); //Returns boolean true
verify( myMock.doThat() ).called(); //Returns boolean false

So, could we be a little more specific?

myMock.doThis([1,2,3], true, "some string");
verify( myMock.doThis([1,2,3], "{any boolean}", "{any string}") ).called("{at least once}"); //Returns true

What were you saying about removing the need for dependency injection?

when( myMock.doThis() ).thenReturn("I'm the mock, not an instance of MyClass");
anyInstance("MyClass", myMock);
new MyClass().doThis(); //Returns "I'm the mock, not an instance of MyClass"
verify( new MyClass() ).called("{1 time}"); //Returns true
new MyClass().doThis(); //Returns "this". 

*After verify() has been called constructors are returned to their original state.

Wow anyInstance() is cool, can I still use the apply/call methods on the overridden constructor?

when( myMock.doThis() ).thenReturn("The mock has been mixed into the child");
anyInstance("MyClass", myMock);

function Child(){
    MyClass.apply(this)
}

new Child().doThis(); //Returns "The mock has been mixed into the child"

How do mosquito ninjas roll?

when( myMock.doThis("{any object}", "number", 1) ).thenReturn("You know that");
anyInstance("MyClass", myMock);
new MyClass(1000, "votes for").doThis({"mosquito": "is"}, "number", 1);
verify( new MyClass("{any number}", "votes for") ).called("{at most once}"); 
verify( myMock.doThis("{any object}", "number", 1) ).called("{at least once}");

Verify is giving me unexpected results, how can I figure out what's wrong?

verify( myMock.doThis() ).history(); //Outputs to the console the details of all calls to this method

Anything else I should know?

Special Strategy Arguments

Curly braces inside strings indicate special strategy arguments that will be evaluated by Mosquito. There are two types of strategy arguments, type strategies and count strategies.

Type strategies:

  • "{any string}"
  • "{any number}"
  • "{any boolean}"
  • "{any object}"
  • "{any array}"
  • "{any function}"
  • "{any value}"
  • "{not null}"

Count strategies:

  • "{n times}"
  • "{n time}"
  • "{at most n}"
  • "{n at most}"
  • "{at least n}"
  • "{n at least}"
  • "{never}"

Globals

In creating Mosquito I have tried hard to keep the global namespace clean whilst at the same time creating an intuitive DSL. At present Mosquito creates four global variables:

  • mock
  • verify
  • when
  • anyInstance

These globals are defined in the last four lines of /src/Mosquito.js and can easily be removed or replaced for other variables:

mock = mosquito.mock;
verify = mosquito.verify;
when = mosquito.when;
anyInstance = mosquito.anyInstance;

Updated