Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/NagRock/ts-mockito
Mocking library for TypeScript
https://github.com/NagRock/ts-mockito
mock-library mocking mockito stub testing typescript
Last synced: 3 months ago
JSON representation
Mocking library for TypeScript
- Host: GitHub
- URL: https://github.com/NagRock/ts-mockito
- Owner: NagRock
- License: mit
- Created: 2016-08-31T20:17:51.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2023-02-12T15:46:06.000Z (almost 2 years ago)
- Last Synced: 2024-10-12T04:01:15.984Z (3 months ago)
- Topics: mock-library, mocking, mockito, stub, testing, typescript
- Language: TypeScript
- Homepage:
- Size: 286 KB
- Stars: 975
- Watchers: 10
- Forks: 93
- Open Issues: 91
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ts-mockito [![build badge](https://travis-ci.org/NagRock/ts-mockito.svg?branch=master)](https://travis-ci.org/NagRock/ts-mockito) [![codecov](https://codecov.io/gh/NagRock/ts-mockito/branch/master/graph/badge.svg)](https://codecov.io/gh/NagRock/ts-mockito)
Mocking library for TypeScript inspired by http://mockito.org/
## 1.x to 2.x migration guide
[1.x to 2.x migration guide](https://github.com/NagRock/ts-mockito/wiki/ts-mockito-1.x-to-2.x-migration-guide)## Main features
* Strongly typed
* IDE autocomplete
* Mock creation (`mock`) (also abstract classes) [#example](#basics)
* Spying on real objects (`spy`) [#example](#spying-on-real-objects)
* Changing mock behavior (`when`) via:
* `thenReturn` - return value [#example](#stubbing-method-calls)
* `thenThrow` - throw an error [#example](#throwing-errors)
* `thenCall` - call custom method [#example](#custom-function)
* `thenResolve` - resolve promise [#example](#resolving--rejecting-promises)
* `thenReject` - rejects promise [#example](#resolving--rejecting-promises)
* Checking if methods were called with given arguments (`verify`)
* `anything`, `notNull`, `anyString`, `anyOfClass` etc. - for more flexible comparision
* `once`, `twice`, `times`, `atLeast` etc. - allows call count verification [#example](#call-count-verification)
* `calledBefore`, `calledAfter` - allows call order verification [#example](#call-order-verification)
* Resetting mock (`reset`, `resetCalls`) [#example](#resetting-mock-calls), [#example](#resetting-mock)
* Capturing arguments passed to method (`capture`) [#example](#capturing-method-arguments)
* Recording multiple behaviors [#example](#recording-multiple-behaviors)
* 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
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);// Getting instance from mock
let foo:Foo = instance(mockedFoo);// Using instance in source code
foo.getBar(3);
foo.getBar(5);// Explicit, readable verification
verify(mockedFoo.getBar(3)).called();
verify(mockedFoo.getBar(anything())).called();
```### Stubbing method calls
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);// stub method before execution
when(mockedFoo.getBar(3)).thenReturn('three');// Getting instance
let foo:Foo = instance(mockedFoo);// prints three
console.log(foo.getBar(3));// prints null, because "getBar(999)" was not stubbed
console.log(foo.getBar(999));
```### Stubbing getter value
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);// stub getter before execution
when(mockedFoo.sampleGetter).thenReturn('three');// Getting instance
let foo:Foo = instance(mockedFoo);// prints three
console.log(foo.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](http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-objects) object is available (ES6).
### Call count verification
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);// Getting instance
let foo:Foo = instance(mockedFoo);// Some calls
foo.getBar(1);
foo.getBar(2);
foo.getBar(2);
foo.getBar(3);// Call count verification
verify(mockedFoo.getBar(1)).once(); // was called with arg === 1 only once
verify(mockedFoo.getBar(2)).twice(); // was called with arg === 2 exactly two times
verify(mockedFoo.getBar(between(2, 3))).thrice(); // was called with arg between 2-3 exactly three times
verify(mockedFoo.getBar(anyNumber()).times(4); // was called with any number arg exactly four times
verify(mockedFoo.getBar(2)).atLeast(2); // was called with arg === 2 min two times
verify(mockedFoo.getBar(anything())).atMost(4); // was called with any argument max four times
verify(mockedFoo.getBar(4)).never(); // was never called with arg === 4
```### Call order verification
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);
let mockedBar:Bar = mock(Bar);// Getting instance
let foo:Foo = instance(mockedFoo);
let bar:Bar = instance(mockedBar);// Some calls
foo.getBar(1);
bar.getFoo(2);// Call order verification
verify(mockedFoo.getBar(1)).calledBefore(mockedBar.getFoo(2)); // foo.getBar(1) has been called before bar.getFoo(2)
verify(mockedBar.getFoo(2)).calledAfter(mockedFoo.getBar(1)); // bar.getFoo(2) has been called before foo.getBar(1)
verify(mockedFoo.getBar(1)).calledBefore(mockedBar.getFoo(999999)); // throws error (mockedBar.getFoo(999999) has never been called)
```### Throwing errors
``` typescript
let mockedFoo:Foo = mock(Foo);when(mockedFoo.getBar(10)).thenThrow(new Error('fatal error'));
let foo:Foo = instance(mockedFoo);
try {
foo.getBar(10);
} catch (error:Error) {
console.log(error.message); // 'fatal error'
}
```### Custom function
You can also stub method with your own implementation
``` typescript
let mockedFoo:Foo = mock(Foo);
let foo:Foo = instance(mockedFoo);when(mockedFoo.sumTwoNumbers(anyNumber(), anyNumber())).thenCall((arg1:number, arg2:number) => {
return arg1 * arg2;
});// prints '50' because we've changed sum method implementation to multiply!
console.log(foo.sumTwoNumbers(5, 10));
```### Resolving / rejecting promises
You can also stub method to resolve / reject promise
``` typescript
let mockedFoo:Foo = mock(Foo);when(mockedFoo.fetchData("a")).thenResolve({id: "a", value: "Hello world"});
when(mockedFoo.fetchData("b")).thenReject(new Error("b does not exist"));
```### Resetting mock calls
You can reset just mock call counter
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);// Getting instance
let foo:Foo = instance(mockedFoo);// Some calls
foo.getBar(1);
foo.getBar(1);
verify(mockedFoo.getBar(1)).twice(); // getBar with arg "1" has been called twice// Reset mock
resetCalls(mockedFoo);// Call count verification
verify(mockedFoo.getBar(1)).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
``` typescript
// Creating mock
let mockedFoo:Foo = mock(Foo);
when(mockedFoo.getBar(1)).thenReturn("one").// Getting instance
let foo:Foo = instance(mockedFoo);// Some calls
console.log(foo.getBar(1)); // "one" - as defined in stub
console.log(foo.getBar(1)); // "one" - as defined in stub
verify(mockedFoo.getBar(1)).twice(); // getBar with arg "1" has been called twice// Reset mock
reset(mockedFoo);// Call count verification
verify(mockedFoo.getBar(1)).never(); // has never been called after reset
console.log(foo.getBar(1)); // null - previously added stub has been removed
```You can also reset multiple mocks at once `reset(firstMock, secondMock, thirdMock)`
### Capturing method arguments
``` typescript
let mockedFoo:Foo = mock(Foo);
let foo:Foo = instance(mockedFoo);// Call method
foo.sumTwoNumbers(1, 2);// Check first arg captor values
const [firstArg, secondArg] = capture(mockedFoo.sumTwoNumbers).last();
console.log(firstArg); // prints 1
console.log(secondArg); // 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
``` typescript
const mockedFoo:Foo = mock(Foo);when(mockedFoo.getBar(anyNumber())).thenReturn('one').thenReturn('two').thenReturn('three');
const foo:Foo = instance(mockedFoo);
console.log(foo.getBar(1)); // one
console.log(foo.getBar(1)); // two
console.log(foo.getBar(1)); // three
console.log(foo.getBar(1)); // three - last defined behavior will be repeated infinitely
```Another example with specific values
``` typescript
let mockedFoo:Foo = mock(Foo);when(mockedFoo.getBar(1)).thenReturn('one').thenReturn('another one');
when(mockedFoo.getBar(2)).thenReturn('two');let foo:Foo = instance(mockedFoo);
console.log(foo.getBar(1)); // one
console.log(foo.getBar(2)); // two
console.log(foo.getBar(1)); // another one
console.log(foo.getBar(1)); // another one - this is last defined behavior for arg '1' so it will be repeated
console.log(foo.getBar(2)); // two
console.log(foo.getBar(2)); // two - this is last defined behavior for arg '2' so it will be repeated
```Short notation:
``` typescript
const mockedFoo:Foo = mock(Foo);// You can specify return values as multiple thenReturn args
when(mockedFoo.getBar(anyNumber())).thenReturn('one', 'two', 'three');const foo:Foo = instance(mockedFoo);
console.log(foo.getBar(1)); // one
console.log(foo.getBar(1)); // two
console.log(foo.getBar(1)); // three
console.log(foo.getBar(1)); // three - last defined behavior will be repeated infinity
```Possible errors:
``` typescript
const mockedFoo:Foo = mock(Foo);// When multiple matchers, matches same result:
when(mockedFoo.getBar(anyNumber())).thenReturn('one');
when(mockedFoo.getBar(3)).thenReturn('one');const foo:Foo = instance(mockedFoo);
foo.getBar(3); // 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``` typescript
let mockedFoo:Foo = mock(); // instead of mock(FooInterface)
const foo: SampleGeneric = instance(mockedFoo);
```### Mocking types
You can mock abstract classes
``` typescript
const mockedFoo: SampleAbstractClass = mock(SampleAbstractClass);
const foo: SampleAbstractClass = instance(mockedFoo);
```You can also mock generic classes, but note that generic type is just needed by mock type definition
``` typescript
const mockedFoo: SampleGeneric = mock(SampleGeneric);
const foo: SampleGeneric = instance(mockedFoo);```
### Spying on real objects
You can partially mock an existing instance:
``` typescript
const foo: Foo = new Foo();
const spiedFoo = spy(foo);when(spiedFoo.getBar(3)).thenReturn('one');
console.log(foo.getBar(3)); // 'one'
console.log(foo.getBaz()); // call to a real method
```You can spy on plain objects too:
``` typescript
const foo = { bar: () => 42 };
const spiedFoo = spy(foo);foo.bar();
console.log(capture(spiedFoo.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)