JavaScript object mocking library based on Mockito syntax for JS unit testing. It goes a bit further by implementing some cool syntax you can achieve in JavaScript using ECMA5 object properties and allowing you to handle mocking global scope functions and match calls on different contexts.
Installation
- Include /src/Mock.js into your tests runtime
- Mock will automatically attach itself to the "window" scope (browser) if it exists
For specific unit testing tools:
- you can use Mock.hookTo(context); to import MockJS tools into your testing scope.
- Currently supports context = "screwunit", "JsUnitTest", "jsUnity", "jSpec", "JsTestDriver", "YUITest", "QUnit";
Or you can send your own context object:
Mock.hookTo(MyTestingTool.globalTestScope);
Quick test / check:
- check and run /src/testception/index.html in your browser (outputs test results in console) Note: the small TestSuite included in testception is a very simplistic tool used to test MockJS itself - MockJS is completely standalone.
Documentation below is divided into 2 main sections:
- Mockito Classics - what you did in Mockito and how to do it in MockJS;
- MockJS Specifics - specific features for mocking JavaScript;
Your Mockito classics (rewritten directly from Mockito's documentation):
1. Verify interactions
var mockArray = Mock([]); //create the mock object
mockArray.push("one");
verify( Acts.once, mockArray.push("one") );
1. Stubbing method calls
when( mockArray.push("one") ).thenReturn(1);
console.log( mockArray.push("one") ); //prints "1"
verify( Acts.once, mockArray.push("one") );
3. Argument matchers
when( mockArray.push(Match.anything) ).thenReturn("hello!");
console.log( mockArray.push("one") ); //prints "hello!"
console.log( mockArray.push(999) ); //prints "hello!"
//look into 102. for more information
4. Verifying exact number of invocations / at least x / never
verify( Acts.never, mockArray.push("one") ); //ok
mockArray.push("one");
verify( Acts.once, mockArray.push("one") ); //ok
verify( Acts.atLeast(1), mockArray.push("one") ); //ok
mockArray.push("one");
mockArray.push("one");
verify( Acts.atMost(2), mockArray.push("one") ); //fails
//look into 103. for more information
5. Stubbing void methods with exceptions
when( mockArray.push(Match.anything) ).thenThrow("Hi, I am an expcetion");
mockArray.push("something"); //throws our exception
11. Stubbing with callbacks
when( mockArray.push(Match.anything) ).thenReturn(function(arg){
console.log("array.push('"+arg+"') called!");
return "hello!";
});
console.log( mockArray.push("one") ); //prints "array.push('one') called!" and "hello!"
12. thenReturn() | thenThow() | thenAnswer() | thenNothing() | thenCallRealMethod() family of methods
Currently implemented:
- thenReturn()
- thenThow()
Not Yet Implemented:
- thenNothing()
- thenCallRealMethod()
Unnecessary in JS: thenAnswer()
15. Capturing arguments for further assertions
//All return callbacks support it by default - take a look at example 11.
18. Troubleshooting & validating framework usage
You should know that MockJS validates if you use it correctly all the time. You have more questions please refer to our issues section on github.
26. Mocking details
Mock.isMock(someObject);
Not Yet Implemented:
- Mock.isSpy
100. Mock in-scope functions
function sum(a, b){
return a+b;
}
var mockSum = Mock(sum);
mockSum(5, 5); //returns undefined (default)
101. Match contexts
when( mockArray.push.apply(Match.anyContext, [Match.anything]) ).thenReturn("something");
mockArray.push.apply([], ["one"]);
verify( Acts.once, mockArray.push.apply(Match.anyContext, [Match.anything]) );
102. Matchers (Match)
//argument matchers
Match.anyString //argument is a string
Match.anyInt //argument is an integer
Match.anyNumber //argument is a number
Match.anyFunction //argument is a function
Match.anything //argument is not undefined
Match.everything //special matcher - all arguments from this point on will be accepted
//eg. when( foo("a", Match.everything) ) will match foo("a"), foo("a", "one"), foo("a", 1, 2, 3, 4, 5, 6);
//context matcher
Match.anyContext //all contexts will be accepted
103. Call Counters (Acts)
Acts.times(x); //verifies call acted exactly x number of times
Acts.never //never happens (short for Acts.times(0))
Acts.once //acts once (short for Acts.times(1))
Acts.atLeast(x) //acts at least x times
Acts.atMost(x) //acts at most x times
//Note: the following syntax should not be used:
var a = Acts.never
verify( a, foo() ); //works 1st time
verify( a, foo("one") ); //throws unexpected action in MockJS on all further uses
verify( Acts.never, foo("one") ); //always use the complete API syntax
104. Custom argument matchers
function myClass(){
}
var matchObjectClass = function(arg){
return arg instanceof myClass;
}
when( foo(matchObjectClass) ).thenReturn("something");
foo(new myClass()); //returns "something"
verify( Acts.once, foo(matchObjectClass) ); //verifies correctly
105. Save and restore global references
//let's consider our global function foo
var foo = function(a){
alert(a);
return "hello";
}
foo = Mock.andSave(foo, "myFoo"); //mocks function foo but keeps a reference for teardown (below)
when( foo(Match.anything) ).thenReturn("hello");
console.log( foo("hey") ); //prints "hello" into console
//teardown
foo = Mock.teardown("myFoo"); //sets foo back to the original function
foo("hey"); //alerts "hey"
106. Mock.new() - create mocks for inacessible objects
//Consider the function we need to mock:
function $(a){
var privateObject = {
whisper:function(){
console.log(a);
return true;
},
say:function(){
alert(a);
return true;
}
}
return privateObject;
}
// Notice we cannot get a "mockable" instance of privateObject
// but we do know it is going to have a method "say"
//our function being tested
function iNeedTesting(){
var check = $("hello");
if(check.whisper() && check.say()) console.log("works!");
}
//let's mock the main wrapper
$ = Mock($);
var privateObject = Mock.new(["whisper", "say"]); //create a mock object with methods "whisper" and "say"
when( $("hello") ).thenReturn(mockPrivateObject);
when( privateObject.whisper() ).thenReturn(true);
when( privateObject.say() ).thenReturn(true);
iNeedTesting(); //run our function being tested - prints out "works!" to console
verify(Acts.once, $("hello"));
verify(Acts.once, privateObject.whisper());
verify(Acts.once, privateObject.say());
//all ok
Stuff on Mockito documentation that we haven't implemented yet
- 6. Verification in order
- 7. Making sure interaction(s) never happened on mock
- 8. Finding redundant invocations
- 10. Stubbing consecutive calls (iterator-style stubbing)
- 13. Spying on real objects
- 14. Changing default return values of unstubbed invocations
- 16. Real partial mocks
- 17. Resetting mocks
- 19. Aliases for behavior driven development
- 20. Serializable mocks
- 21. New annotations: @Captor, @Spy, @InjectMocks //Note: Probably Not Applicable
- 22. Verification with timeout
- 23. Automatic instantiation of @Spies, @InjectMocks and constructor injection goodness //Note: Probably Not Applicable
- 24. One-liner stubs
- 25. Verification ignoring stubs
- 27. Delegate calls to real instance //Note: Probably Not Applicable
- 28. MockMaker API //Note: Probably Not Applicable
Something extra we would like to do:
- 107. Make it available as a npm package (Node.js)
Pull requests anyone? :p
This special cocktail is brought to you by Badoo Trading Limited and it is released under the MIT License
Created by Carlos Ouro