0.8.1 • Published 21 days ago
mockt v0.8.1
Getting Started
Npm:
$ npm install --save-dev mockt
Yarn:
$ yarn add -D mockt
Now let's write a simple test:
const calculator = mockt(Calculator)
when(calculator).sum(2, any()).returns(3)
const actual = calculator.sum(2, 8)
expect(actual).toEqual(3)
verify(calculator).sum(any(), 8)
Features
- Typescript Support and IDE Autocompletion
- Class mocks
- Abstract class mocks
- Interface mocks
- Generics support
- Flexible stubbing with multiple returns, custom function call, errors, promises and stub overriding.
- Properties stubbing
- Spy on real objects
- Argument Capturing
- Verification atLeast, atMost, once, times(n)
- Verification called and never called
- Properties read and write verification
- Verification order
- Argument Matchers for stubs and verifications
- Reset mock stubs
- Reset mock recorded calls
Table of Contents
- Usage
- Class mocks
- Abstract Class mocks
- Interface mocks
- Generics
- Properties
- Stubbing
- Matchers
- Verification
- Verify method called
- Verify property read
- Verify property set
- Verify method called at least n times
- Verify method called at most n times
- Verify method called exactly n times
- Verify method never called
- Verify multiple method calls
- Verify multiple methods never called
- Verify multiple methods called in expected order
- Verify sequence of calls from different mocks or spies
- Capture arguments
- Spies
- Reset
Usage
Class mocks
class Calculator {
sum(a: number, b: number): number {
return a + b
}
}
const calculator = mockt(Calculator)
when(calculator).sum(2, 3).returns(5)
calculator.sum(2, 3) // returns 5
Arrow methods
class Calculator {
sum = (a: number, b: number) => a + b
}
const calculator = mockt(Calculator)
when(calculator).sum(2, 3).returns(5)
calculator.sum(2, 3) // returns 5
Note: arrow methods fails when called without stubbing them.
Abstract Class mocks
abstract class Calculator {
abstract sum(a: number, b: number): number
}
const calculator = mockt(Calculator)
when(calculator).sum(2, 3).returns(5)
calculator.sum(2, 3) // returns 5
Note: abstract methods fails when called without stubbing them.
Interface mocks
interface Calculator {
sum(a: number, b: number): number
}
const calculator = mockt<Calculator>()
when(calculator).sum(2, 3).returns(5)
calculator.sum(2, 3) // returns 5
Note: Interfaces are passed as Generic Parameter to mockt function.
Note: Interface methods fails when called without stubbing them.
Generics
interface List<T> {
add(item: T): void
get(index: number): T
}
const list = mockt(List<string>)
when(list).get(3).returns('Item 3')
list.get(3) // returns 'Item 3'
Properties
class User {
public name: string
}
const user = mockt(User)
when(user).name.returns('Alice')
user.name // returns 'Alice'
Getters
class User {
private _name: string
get name(): string {
return this._name
}
}
const user = mockt(User)
when(user).name.returns('Alice')
user.name // returns 'Alice'
Stubbing
Multiple returns
const calculator = mockt(Calculator)
when(calculator).sum(2, 3).returns(5, 6, 7)
calculator.sum(2, 3) // returns 5
calculator.sum(2, 3) // returns 6
calculator.sum(2, 3) // returns 7
calculator.sum(2, 3) // returns 7
Stub overriding
const calculator = mockt(Calculator)
when(calculator).sum(2, 3).returns(5)
when(calculator).sum(2, 3).returns(6)
calculator.sum(2, 3) // returns 6
calculator.sum(2, 3) // returns 6
const calculator = mockt(Calculator)
when(calculator).sum(any(), any()).returns(5, 6)
when(calculator).sum(2, 3).returns(7)
calculator.sum(2, 3) // returns 7
calculator.sum(2, 4) // returns 5
calculator.sum(2, 5) // returns 6
Function call
const calculator = mockt(Calculator)
when(calculator).sum(any(), any()).calls((a, b) => a * b)
calculator.sum(2, 3) // returns 6
calculator.sum(3, 4) // returns 12
Throw error
const calculator = mockt(Calculator)
when(calculator).sum(any(), any()).throws(new Error('Some error'))
calculator.sum(2, 3) // throws Error('Some error')
Promise resolve
const apiClient = mockt(ApiClient)
when(apiClient).getUser().resolves(user1, user2)
await apiClient.getUser() // returns user 1
await apiClient.getUser() // returns user 2
Promise reject
const apiClient = mockt(ApiClient)
when(apiClient).getUser().rejects(new Error('Some error'))
await apiClient.getUser() // throws Error('Some error')
Chained answers
const calculator = mockt(Calculator)
when(calculator).sum(2, 3)
.returns(5)
.returns(6)
.calls(() => 7)
.throws(new Error('Some error'))
calculator.sum(2, 3) // returns 5
calculator.sum(2, 3) // returns 6
calculator.sum(2, 3) // returns 7
calculator.sum(2, 3) // throws Error('Some error')
Matchers
Equals
const calculator = mockt(Calculator)
when(calculator).sum(2, eq(3)).returns(5)
calculator.sum(2, 3) // returns 5
calculator.sum(2, 4) // returns undefined
Note: When a value is given instead of a matcher, the equals matcher is used. Note: Performs deep equality
Deep equality and type conversion
const billingService = mockt(BillingService)
when(billingService).calculateFor(eq({ user: { age: '17' } })).returns(100)
billingService.calculateFor({ user: { age: 17 } }) // returns 100
Not Equals
const calculator = mockt(Calculator)
when(calculator).sum(2, neq(3)).returns(5)
calculator.sum(2, 6) // returns 5
calculator.sum(2, 3) // returns undefined
Identical
const billingService = mockt(BillingService)
const alice = { name: 'Alice' }
when(billingService).calculateFor(is(alice)).returns(100)
billingService.calculateFor(alice) // returns 100
billingService.calculateFor({ name: 'Alice' }) // returns undefined
Any
const calculator = mockt(Calculator)
when(calculator).sum(2, any()).returns(5)
calculator.sum(2, 5) // returns 5
calculator.sum(2, 6) // returns 5
calculator.sum(3, 5) // returns undefined
Any Number
const calculator = mockt(Calculator)
when(calculator).sum(anyNumber(), any()).returns(5)
calculator.sum(1, 2) // returns 10
calculator.sum('1', 2) // returns undefined
calculator.sum(1, '2') // returns 10
Any String
const splitter = mockt(StringSplitter)
when(splitter).split(anyString()).returns(['Hello', 'World'])
splitter.split('Hello World') // returns ['Hello', 'World']
splitter.split('Bye') // returns ['Hello', 'World']
splitter.split(3) // returns undefined
Any Array
const calculator = mockt(Calculator)
when(calculator).average(anyArray()).returns(10)
calculator.average([1, 2]) // returns 10
calculator.average([3, 4]) // returns 10
calculator.average([]) // returns 10
calculator.average(3) // returns undefined
Any Object
const billingService = mockt(BillingService)
when(billingService).calculateFor(anyObject()).returns(2000)
billingService.calculateFor({ name: 'Alice', lastname: 'Jones' }) // returns 2000
billingService.calculateFor({}) // returns 2000
billingService.calculateFor('alice') // returns undefined
Any Function
const caller = mockt(FunctionCalled)
when(caller).call(anyFunction()).returns(10)
caller.call(() => {}) // returns 10
caller.call(function () {}) // returns 10
caller.call('alice') // returns undefined
IsNull
const billingService = mockt(BillingService)
when(billingService).calculateFor(isNull()).throws(new Error('User cannot be null'))
billingService.calculateFor(null) // throws Error('User cannot be null')
billingService.calculateFor({ name: 'Alice' }) // Doesn't throw
billingService.calculateFor(undefined) // Doesn't throw
billingService.calculateFor('') // Doesn't throw
billingService.calculateFor([]) // Doesn't throw
IsNil
const billingService = mockt(BillingService)
when(billingService).calculateFor(isNil()).throws(new Error('User cannot be null'))
billingService.calculateFor(null) // throws Error('User cannot be null')
billingService.calculateFor(undefined) // throws Error('User cannot be null')
billingService.calculateFor({ name: 'Alice' }) // Doesn't throw
billingService.calculateFor('') // Doesn't throw
billingService.calculateFor([]) // Doesn't throw
NotNull
const billingService = mockt(BillingService)
when(billingService).calculateFor(notNull()).returns(5000)
billingService.calculateFor({ name: 'Alice' }) // returns 5000
billingService.calculateFor(undefined) // returns 5000
billingService.calculateFor(null) // returns undefined
NotNil
const billingService = mockt(BillingService)
when(billingService).calculateFor(notNil()).returns(5000)
billingService.calculateFor({ name: 'Alice' }) // returns 5000
billingService.calculateFor(undefined) // returns undefined
billingService.calculateFor(null) // returns undefined
Less
const calculator = mockt(Calculator)
when(calculator).sum(less(5), any()).returns(10)
calculator.sum(4, 2) // returns 10
calculator.sum(5, 2) // returns 10
calculator.sum(6, 2) // returns undefined
More
const calculator = mockt(Calculator)
when(calculator).sum(more(5), any()).returns(10)
calculator.sum(6, 2) // returns 10
calculator.sum(5, 2) // returns 10
calculator.sum(4, 2) // returns undefined
Range
const calculator = mockt(Calculator)
when(calculator).sum(range(5, 10), any()).returns(10)
calculator.sum(4, 2) // returns undefined
calculator.sum(5, 2) // returns 10
calculator.sum(6, 2) // returns 10
calculator.sum(9, 2) // returns 10
calculator.sum(10, 2) // returns 10
calculator.sum(11, 2) // returns undefined
OfClass
const billingService = mockt(BillingService)
when(billingService).calculateFor(ofClass(Employee)).returns(2000)
billingService.calculateFor(new Employee('Alice')) // returns 2000
billingService.calculateFor(new User('Alice')) // returns undefined
Nested matchers
const billingService = mockt(BillingService)
when(billingService).calculateFor(eq({ name: 'Alice', lastname: any() })).returns(2000)
billingService.calculateFor({ name: 'Alice', lastname: 'Jones' }) // returns 2000
const calculator = mockt(Calculator)
when(calculator).average(eq([1, any(), 3])).returns(1)
calculator.average([1, 2, 3]) // returns 1
Not
const calculator = mockt(Calculator)
when(calculator).sum(not(anyNumber()), any()).returns(10)
calculator.sum('5', 2) // returns 10
calculator.sum(5, 2) // returns undefined
And
const calculator = mockt(Calculator)
when(calculator).sum(and(neq(2), neq(3)), any()).returns(10)
calculator.sum(1, 2) // returns 10
calculator.sum(2, 2) // returns undefined
calculator.sum(3, 2) // returns undefined
Or
const calculator = mockt(Calculator)
when(calculator).sum(or(2, 3), any()).returns(10)
calculator.sum(2, 2) // returns 10
calculator.sum(3, 2) // returns 10
calculator.sum(1, 2) // returns undefined
Verification
Verify method called
const calculator = mockt(Calculator)
calculator.sum(1, 2)
verify(calculator).sum(1, 2) // passes
verify(calculator).sum(any(), 2) // passes
verify(calculator).sum(2, 2) // fails
Verify property read
const user = mockt(User)
const name = user.name
verify(user).getProperty('name') // passes
verify(user).getProperty('lastname') // fails
Verify property set
const user = mockt(User)
user.name = 'Alice'
verify(user).setProperty('name', 'Alice') // passes
verify(user).setProperty('name', any()) // passes
verify(user).setProperty('name', 'Bob') // fails
Verify method called at least n times
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(3, 4)
calculator.sum(5, 6)
verifyAtLeast(2, calculator).sum(any(), any()) // passes
verifyAtLeast(3, calculator).sum(any(), any()) // passes
verifyAtLeast(4, calculator).sum(any(), any()) // fails
Verify method called at most n times
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyAtMost(4, calculator).sum(1, any()) // passes
verifyAtMost(3, calculator).sum(1, any()) // passes
verifyAtMost(2, calculator).sum(1, any()) // fails
Verify method called exactly n times
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyTimes(3, calculator).sum(1, any()) // passes
verifyTimes(2, calculator).sum(1, any()) // fails
Verify method never called
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyNever(calculator).sum(1, 1) // passes
verifyNever(calculator).sum(1, 2) // fails
Verify multiple method calls
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyMulti(calculator)
.sum(1, 2)
.sum(1, 4)
.called() // passes
Verify multiple methods never called
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyMulti(calculator)
.sum(2, 2)
.sum(2, 4)
.never() // passes
Verify multiple methods called in expected order
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyMulti(calculator)
.sum(1, 2)
.sum(1, 4)
.calledInOrder() // passes
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
calculator.sum(1, 4)
verifyMulti(calculator)
.sum(1, 4)
.sum(1, 2)
.calledInOrder() // fails
Verify sequence of calls from different mocks or spies
import { verifySequence } from './verifySequence'
const billingService = mockt<BillingService>()
const deliveryService = mockt<DeliveryService>()
billingService.createFor(customer, products)
deliveryService.deliveryFor(customer.address, products)
verifySequence()
.call(billingService).createFor(any(), any())
.call(deliveryService).deliveryFor(any(), any()) // passes
Capture arguments
Last call
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
const [first, second] = capture(calculator).sum // returns [1, 3]
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
const [first, second] = captureLast(calculator).sum // returns [1, 3]
First call
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
const [first, second] = captureFirst(calculator).sum // returns [1, 2]
All calls
const calculator = mockt(Calculator)
calculator.sum(1, 2)
calculator.sum(1, 3)
const args = captureAll(calculator).sum // returns [[1, 2], [1, 3]]
Setters
const user = mockt(User)
user.name = 'Alice'
const [name] = capture(user).setProperty('name') // returns 'Alice'
Spies
const calculator = new Calculator()
const calculatorSpy = spy(calculator)
calculator.sum(1, 2) // returns 3
verify(calculatorSpy).sum(1, 2) // passes
verify(calculatorSpy).sum(2, 2) // fails
Reset
Calls
const calculator = mockt(Calculator)
calculator.sum(1, 2) // returns undefined
verify(calculatorSpy).sum(1, 2) // passes
resetCalls(calculator)
verify(calculatorSpy).sum(1, 2) // fails
All
const calculator = mockt(Calculator)
calculator.sum(1, 2) // returns undefined
verify(calculatorSpy).sum(1, 2) // passes
reset(calculator)
verify(calculatorSpy).sum(1, 2) // fails
const calculator = mockt(Calculator)
when(calculator).sum(2, any()).returns(3)
reset(calculator)
calculator.sum(1, 2) // returns undefined
Credits
Thanks to all the contributors of ts-mockito and Mockk.
0.8.1
21 days ago
0.8.0
21 days ago
0.7.1
24 days ago
0.7.0
24 days ago
0.6.1
25 days ago
0.6.0
25 days ago
0.5.5
25 days ago
0.5.4
25 days ago
0.5.3
25 days ago
0.5.2
25 days ago
0.5.1
25 days ago
0.5.0
25 days ago
0.4.1
25 days ago
0.4.0
26 days ago
0.3.0
26 days ago
0.2.6
26 days ago
0.2.5
26 days ago
0.2.4
26 days ago
0.2.3
26 days ago
0.2.2
26 days ago
0.2.1
27 days ago
0.2.0
27 days ago
0.1.0
27 days ago