0.8.1 • Published 21 days ago

mockt v0.8.1

Weekly downloads
-
License
MIT
Repository
github
Last release
21 days ago

npm License: MIT CI Status

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

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