Mocking library for TypeScript inspired by http://mockito.org/
1.x to 2.x migration guide
Main features
- Strongly typed
- IDE autocomplete
- Mock creation (
mock
) (also abstract classes) #example - Spying on real objects (
spy
) #example - Changing mock behavior (
when
) via: - Checking if methods were called with given arguments (
verify
) - Resetting mock (
reset
,resetCalls
) #example, #example - Capturing arguments passed to method (
capture
) #example - Recording multiple behaviors #example
- Readable error messages (ex.
'Expected "convertNumberToString(strictEqual(3))" to be called 2 time(s). But has been called 1 time(s).'
)
Installation
npm install ts-mockito --save-dev
Usage
Basics
// Creating mock;// Getting instance from mock;// Using instance in source codefoo.getBar3;foo.getBar5;// Explicit, readable verificationverifymockedFoo.getBar3.called;verifymockedFoo.getBar5.called;
Stubbing method calls
// Creating mock;// stub method before executionwhenmockedFoo.getBar3.thenReturn'three';// Getting instance;// prints threeconsole.logfoo.getBar3;// prints null, because "getBar(999)" was not stubbedconsole.logfoo.getBar999;
Stubbing getter value
// Creating mock;// stub getter before executionwhenmockedFoo.sampleGetter.thenReturn'three';// Getting instance;// prints threeconsole.logfoo.sampleGetter;
Stubbing property values that have no getters
Syntax is the same as with getter values.
Please note, that stubbing properties that don't have getters only works if Proxy object is available (ES6).
Call count verification
// Creating mock;// Getting instance;// Some callsfoo.getBar1;foo.getBar2;foo.getBar2;foo.getBar3;// Call count verificationverifymockedFoo.getBar1.once; // was called with arg === 1 only onceverifymockedFoo.getBar2.twice; // was called with arg === 2 exactly two timesverifymockedFoo.getBarbetween2, 3.thrice; // was called with arg between 2-3 exactly three timesverifymockedFoo.getBaranyNumber.times4; // was called with any number arg exactly four timesverifymockedFoo.getBar2.atLeast2; // was called with arg === 2 min two timesverifymockedFoo.getBar1.atMost1; // was called with arg === 1 max one timeverifymockedFoo.getBar4.never; // was never called with arg === 4
Call order verification
// Creating mock;;// Getting instance;;// Some callsfoo.getBar1;bar.getFoo2;// Call order verificationverifymockedFoo.getBar1.calledBeforemockedBar.getFoo2; // foo.getBar(1) has been called before bar.getFoo(2)verifymockedBar.getFoo2.calledAftermockedFoo.getBar1; // bar.getFoo(2) has been called before foo.getBar(1)verifymockedFoo.getBar1.calledBeforemockedBar.getFoo999999; // throws error (mockedBar.getFoo(999999) has never been called)
Throwing errors
;whenmockedFoo.getBar10.thenThrownew Error'fatal error';;trycatch
Custom function
You can also stub method with your own implementation
;;whenmockedFoo.sumTwoNumbersanyNumber, anyNumber.thenCall;// prints '50' because we've changed sum method implementation to multiply!console.logfoo.sumTwoNumbers5, 10;
Resolving / rejecting promises
You can also stub method to resolve / reject promise
;whenmockedFoo.fetchData"a".thenResolve;whenmockedFoo.fetchData"b".thenRejectnew Error"b does not exist";
Resetting mock calls
You can reset just mock call counter
// Creating mock;// Getting instance;// Some callsfoo.getBar1;foo.getBar1;verifymockedFoo.getBar1.twice; // getBar with arg "1" has been called twice// Reset mockresetCallsmockedFoo;// Call count verificationverifymockedFoo.getBar1.never; // has never been called after reset
You can also reset calls of multiple mocks at once resetCalls(firstMock, secondMock, thirdMock)
Resetting mock
Or reset mock call counter with all stubs
// Creating mock;whenmockedFoo.getBar1.thenReturn"one".// Getting instance;// Some callsconsole.logfoo.getBar1; // "one" - as defined in stubconsole.logfoo.getBar1; // "one" - as defined in stubverifymockedFoo.getBar1.twice; // getBar with arg "1" has been called twice// Reset mockresetmockedFoo;// Call count verificationverifymockedFoo.getBar1.never; // has never been called after resetconsole.logfoo.getBar1; // null - previously added stub has been removed
You can also reset multiple mocks at once reset(firstMock, secondMock, thirdMock)
Capturing method arguments
;;// Call methodfoo.sumTwoNumbers1, 2;// Check first arg captor values;console.logfirstArg; // prints 1console.logsecondArg; // prints 2
You can also get other calls using first()
, second()
, byCallIndex(3)
and more...
Recording multiple behaviors
You can set multiple returning values for same matching values
;whenmockedFoo.getBaranyNumber.thenReturn'one'.thenReturn'two'.thenReturn'three';;console.logfoo.getBar1; // oneconsole.logfoo.getBar1; // twoconsole.logfoo.getBar1; // threeconsole.logfoo.getBar1; // three - last defined behavior will be repeated infinitely
Another example with specific values
;whenmockedFoo.getBar1.thenReturn'one'.thenReturn'another one';whenmockedFoo.getBar2.thenReturn'two';;console.logfoo.getBar1; // oneconsole.logfoo.getBar2; // twoconsole.logfoo.getBar1; // another oneconsole.logfoo.getBar1; // another one - this is last defined behavior for arg '1' so it will be repeatedconsole.logfoo.getBar2; // twoconsole.logfoo.getBar2; // two - this is last defined behavior for arg '2' so it will be repeated
Short notation:
;// You can specify return values as multiple thenReturn argswhenmockedFoo.getBaranyNumber.thenReturn'one', 'two', 'three';;console.logfoo.getBar1; // oneconsole.logfoo.getBar1; // twoconsole.logfoo.getBar1; // threeconsole.logfoo.getBar1; // three - last defined behavior will be repeated infinity
Possible errors:
;// When multiple matchers, matches same result:whenmockedFoo.getBaranyNumber.thenReturn'one';whenmockedFoo.getBar3.thenReturn'one';;foo.getBar3; // MultipleMatchersMatchSameStubError will be thrown, two matchers match same method call
Mocking interfaces
You can mock interfaces too, just instead of passing type to mock
function, set mock
function generic type
Mocking interfaces requires Proxy
implementation
; // instead of mock(FooInterface);
Mocking types
You can mock abstract classes
;;
You can also mock generic classes, but note that generic type is just needed by mock type definition
;;
Spying on real objects
You can partially mock an existing instance:
;;whenspiedFoo.getBar3.thenReturn'one';console.logfoo.getBar3; // 'one'console.logfoo.getBaz; // call to a real method
You can spy on plain objects too:
;;foo.bar;console.logcapturespiedFoo.bar.last; // [42]
Thanks
- Szczepan Faber (https://www.linkedin.com/in/szczepiq)
- Sebastian Konkol (https://www.linkedin.com/in/sebastiankonkol)
- Clickmeeting (http://clickmeeting.com)
- Michał Stocki (https://github.com/michalstocki)
- Łukasz Bendykowski (https://github.com/viman)
- Andrey Ermakov (https://github.com/dreef3)
- Markus Ende (https://github.com/Markus-Ende)
- Thomas Hilzendegen (https://github.com/thomashilzendegen)
- Johan Blumenberg (https://github.com/johanblumenberg)