Skip to content

Mock Matchers

Mock matchers help you test the behavior of mock functions by verifying they were called with specific arguments, returned expected values, and more.

toHaveBeenCalled

Verifies that a mock function has been called at least once.

ts
expect(mockFn).toHaveBeenCalled()

Examples

ts
// Creating a mock function
const mockFn = xJet.fn()

// After calling the mock
mockFn()
expect(mockFn).toHaveBeenCalled() // Passes

// When the mock hasn't been called
const unusedMock = xJet.fn()
expect(unusedMock).not.toHaveBeenCalled() // Passes

toHaveBeenCalledTimes

Verifies that a mock function has been called an exact number of times.

ts
expect(mockFn).toHaveBeenCalledTimes(expectedCount)

Parameters

  • expectedCount: The exact number of times the mock should have been called

Examples

ts
const mockFn = xJet.fn()

// No calls
expect(mockFn).toHaveBeenCalledTimes(0) // Passes

// After multiple calls
mockFn()
mockFn()
mockFn()
expect(mockFn).toHaveBeenCalledTimes(3) // Passes
expect(mockFn).not.toHaveBeenCalledTimes(2) // Passes

toHaveBeenCalledWith

Verifies that a mock function has been called with specified arguments at least once.

ts
expect(mockFn).toHaveBeenCalledWith(...expectedArgs)

INFO

🚀 Supports asymmetric matchers

Parameters

  • ...expectedArgs: The expected arguments that the mock function should have been called with

Examples

ts
const mockFn = xJet.fn()

// Basic usage
mockFn('hello', 123)
expect(mockFn).toHaveBeenCalledWith('hello', 123) // Passes

// Multiple calls with different arguments
mockFn('first call')
mockFn('second call')
expect(mockFn).toHaveBeenCalledWith('first call') // Passes
expect(mockFn).toHaveBeenCalledWith('second call') // Passes
expect(mockFn).not.toHaveBeenCalledWith('never called') // Passes

// With objects
mockFn({ name: 'John', age: 30 })
expect(mockFn).toHaveBeenCalledWith({ name: 'John', age: 30 }) // Passes

// With asymmetric matchers
mockFn('hello world', { id: 123, data: [1, 2, 3] })
expect(mockFn).toHaveBeenCalledWith(
  expect.stringContaining('hello'),
  expect.objectContaining({ id: 123 })
) // Passes

toHaveBeenLastCalledWith

Verifies that the last call to a mock function was with specified arguments.

ts
expect(mockFn).toHaveBeenLastCalledWith(...expectedArgs)

INFO

🚀 Supports asymmetric matchers

Parameters

  • ...expectedArgs: The expected arguments of the last call to the mock function

Examples

ts
const mockFn = xJet.fn()

// Multiple calls with different arguments
mockFn('first call')
mockFn('second call')
mockFn('last call')

expect(mockFn).toHaveBeenLastCalledWith('last call') // Passes
expect(mockFn).not.toHaveBeenLastCalledWith('first call') // Passes

// With asymmetric matchers
mockFn({ type: 'final', id: 42 })
expect(mockFn).toHaveBeenLastCalledWith(
  expect.objectContaining({ type: 'final' })
) // Passes

toHaveBeenNthCalledWith

Verifies that the nth call to a mock function was with specified arguments.

ts
expect(mockFn).toHaveBeenNthCalledWith(n, ...expectedArgs)

INFO

🚀 Supports asymmetric matchers

Parameters

  • n: The call number to check (1-based index)
  • ...expectedArgs: The expected arguments of the nth call

Examples

ts
const mockFn = xJet.fn()

// Series of calls with different arguments
mockFn('first')
mockFn('second')
mockFn('third')

expect(mockFn).toHaveBeenNthCalledWith(1, 'first') // Passes
expect(mockFn).toHaveBeenNthCalledWith(2, 'second') // Passes
expect(mockFn).toHaveBeenNthCalledWith(3, 'third') // Passes
expect(mockFn).not.toHaveBeenNthCalledWith(2, 'first') // Passes

// With complex arguments and asymmetric matchers
mockFn(1, { a: 'one' })
mockFn(2, { a: 'two' })
expect(mockFn).toHaveBeenNthCalledWith(
  5, 
  2, 
  expect.objectContaining({ a: 'two' })
) // Passes

toHaveReturned

Verifies that a mock function successfully returned at least once (did not throw).

ts
expect(mockFn).toHaveReturned()

Examples

ts
// Mock that returns normally
const successMock = xJet.fn(() => true)
successMock()
expect(successMock).toHaveReturned() // Passes

// Mock that throws
const failMock = xJet.fn(() => { throw new Error('Failed') })
try {
  failMock()
} catch (e) {
  // Ignore error
}
expect(failMock).not.toHaveReturned() // Passes

// Mixed behavior
const mixedMock = xJet.fn(x => {
  if (x < 0) throw new Error('Negative')
  return x * 2
})

try { mixedMock(-1) } catch (e) { /* Ignore */ }
mixedMock(5)

expect(mixedMock).toHaveReturned() // Passes - returned at least once

toHaveReturnedTimes

Verifies that a mock function successfully returned exactly n times.

ts
expect(mockFn).toHaveReturnedTimes(expectedCount)

Parameters

  • expectedCount: The exact number of times the mock should have returned

Examples

ts
const mockFn = xJet.fn(x => x * 2)

mockFn(1)
mockFn(2)
mockFn(3)

expect(mockFn).toHaveReturnedTimes(3) // Passes

// With some errors
const mixedMock = xJet.fn(x => {
  if (x < 0) throw new Error('Negative')
  return x * 2
})

mixedMock(1)
try { mixedMock(-1) } catch (e) { /* Ignore */ }
mixedMock(2)

expect(mixedMock).toHaveReturnedTimes(2) // Passes - only counts successful returns

toHaveLastReturnedWith

Verifies that the last return value of a mock function matches the expected value.

ts
expect(mockFn).toHaveLastReturnedWith(expectedValue)

INFO

🚀 Supports asymmetric matchers

Parameters

  • expectedValue: The value that should match the last return of the mock function

Examples

ts
const mockFn = xJet.fn()
mockFn.mockReturnValueOnce('first result')
mockFn.mockReturnValueOnce('second result')
mockFn.mockReturnValue('default result')

mockFn() // Returns 'first result'
mockFn() // Returns 'second result'
mockFn() // Returns 'default result'

expect(mockFn).toHaveLastReturnedWith('default result') // Passes
expect(mockFn).not.toHaveLastReturnedWith('second result') // Passes

// With asymmetric matchers
const dataMock = xJet.fn().mockReturnValue({ id: 42, timestamp: Date.now() })
dataMock()
expect(dataMock).toHaveLastReturnedWith(
  expect.objectContaining({ id: 42 })
) // Passes

toHaveNthReturnedWith

Verifies that the nth return value of a mock function matches the expected value.

ts
expect(mockFn).toHaveNthReturnedWith(n, expectedValue)

INFO

🚀 Supports asymmetric matchers

Parameters

  • n: The call number to check (1-based index)
  • expectedValue: The value that should match the nth return of the mock function

Examples

ts
const mockFn = xJet.fn()
  .mockReturnValueOnce('first')
  .mockReturnValueOnce('second')
  .mockReturnValueOnce('third')

mockFn() // Returns 'first'
mockFn() // Returns 'second'
mockFn() // Returns 'third'

expect(mockFn).toHaveNthReturnedWith(1, 'first') // Passes
expect(mockFn).toHaveNthReturnedWith(2, 'second') // Passes
expect(mockFn).toHaveNthReturnedWith(3, 'third') // Passes
expect(mockFn).not.toHaveNthReturnedWith(2, 'third') // Passes

// With asymmetric matchers
const complexMock = xJet.fn()
  .mockReturnValueOnce({ type: 'user', data: { id: 1 } })
  .mockReturnValueOnce({ type: 'post', data: { id: 2 } })

complexMock()
complexMock()

expect(complexMock).toHaveNthReturnedWith(
  1, 
  expect.objectContaining({ type: 'user' })
) // Passes

Common Testing Patterns

Testing Callback Arguments

ts
test('callback is called with correct arguments', () => {
  const mockCallback = xJet.fn()
  
  // Function that accepts a callback
  function processData(data, callback) {
    // Do something with data
    callback(data.id, data.value)
  }
  
  processData({ id: 123, value: 'test' }, mockCallback)
  
  expect(mockCallback).toHaveBeenCalledWith(123, 'test')
})

Testing API Requests

ts
test('API endpoint is called with correct parameters', async () => {
  // Mock the fetch function
  global.fetch = xJet.fn().mockResolvedValue({
    ok: true,
    json: async () => ({ success: true })
  })
  
  // Function that makes API call
  await fetchUserData(42, 'full')
  
  // Verify the API was called correctly
  expect(fetch).toHaveBeenCalledWith(
    'https://api.example.com/users/42?profile=full',
    expect.objectContaining({
      method: 'GET',
      headers: expect.objectContaining({
        'Content-Type': 'application/json'
      })
    })
  )
})

Testing Call Order

ts
test('operations are performed in the correct sequence', () => {
  const logger = xJet.fn()
  
  function performOperations() {
    logger('Starting')
    // Do something
    logger('Processing')
    // Do something else
    logger('Completed')
  }
  
  performOperations()
  
  expect(logger).toHaveBeenNthCalledWith(1, 'Starting')
  expect(logger).toHaveBeenNthCalledWith(2, 'Processing')
  expect(logger).toHaveBeenNthCalledWith(3, 'Completed')
  expect(logger).toHaveBeenCalledTimes(3)
})

Testing Conditional Logic

ts
test('conditional function calls', () => {
  const mockFn = xJet.fn()
  
  function processValue(value) {
    if (value > 0) {
      mockFn(`Positive: ${value}`)
    } else if (value < 0) {
      mockFn(`Negative: ${value}`)
    } else {
      mockFn('Zero')
    }
  }
  
  processValue(5)
  processValue(-3)
  processValue(0)
  
  expect(mockFn).toHaveBeenCalledWith('Positive: 5')
  expect(mockFn).toHaveBeenCalledWith('Negative: -3')
  expect(mockFn).toHaveBeenCalledWith('Zero')
  expect(mockFn).toHaveBeenCalledTimes(3)
})

Testing Return Values

ts
test('function returns expected values', () => {
  const transformData = xJet.fn()
    .mockReturnValueOnce({ transformed: true, id: 1 })
    .mockReturnValueOnce({ transformed: true, id: 2 })
  
  const result1 = transformData({ id: 1 })
  const result2 = transformData({ id: 2 })
  
  expect(transformData).toHaveNthReturnedWith(1, { transformed: true, id: 1 })
  expect(transformData).toHaveLastReturnedWith({ transformed: true, id: 2 })
  expect(transformData).toHaveReturnedTimes(2)
})

Testing Event Handlers

ts
test('event handlers are called correctly', () => {
  // Mock event handlers
  const onSuccess = xJet.fn()
  const onError = xJet.fn()
  const onComplete = xJet.fn()
  
  // Function with event handlers
  function processWithEvents(data, options) {
    try {
      // Processing
      if (data.valid) {
        onSuccess(data.result)
      } else {
        onError(new Error('Invalid data'))
      }
    } finally {
      onComplete()
    }
  }
  
  // Test success path
  processWithEvents({ valid: true, result: 'success' })
  expect(onSuccess).toHaveBeenCalledWith('success')
  expect(onError).not.toHaveBeenCalled()
  expect(onComplete).toHaveBeenCalled()
  
  // Reset mocks
  xJet.clearAllMocks()
  
  // Test error path
  processWithEvents({ valid: false })
  expect(onSuccess).not.toHaveBeenCalled()
  expect(onError).toHaveBeenCalledWith(expect.any(Error))
  expect(onComplete).toHaveBeenCalled()
})