Skip to content

Commit

Permalink
Support resetting of specific calledWith mocks
Browse files Browse the repository at this point in the history
  • Loading branch information
timkindberg committed Dec 3, 2024
1 parent 4476ba5 commit ce60dd5
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 3 deletions.
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,19 +347,50 @@ You could use this to prevent mocks from carrying state between tests or asserti
const { when, resetAllWhenMocks } = require('jest-when')
const fn = jest.fn()

// Test 1
when(fn).expectCalledWith(1).mockReturnValueOnce('x')

expect(fn(1)).toEqual('x')

resetAllWhenMocks()

// Test 2
when(fn).expectCalledWith(1).mockReturnValueOnce('z')

expect(fn(1)).toEqual('z')
```

Thanks to [@whoaa512](https://github.com/whoaa512).

#### Supports resetting individual mocks entirely or by matchers

You can reset a single mocked function by calling `mockReset` on the mock function.

```javascript
const fn = jest.fn()

when(fn).calledWith(1).mockReturnValue('yay!')
when(fn).calledWith(2).mockReturnValue('boo!')
fn.mockReset()

expect(fn(1)).toBeUndefined() // no mocks
expect(fn(2)).toBeUndefined() // no mocks
```

You can reset a single set of matchers by calling `mockReset` after `calledWith`. The matchers
passed to calledWith will be used to remove any existing `calledWith` trainings with the same mathers.

```javascript
const fn = jest.fn()

when(fn).calledWith(1, 2, 3).mockReturnValue('yay!')
when(fn).calledWith(2).mockReturnValue('boo!')

// Reset only the 1, 2, 3 mock call
when(fn).calledWith(1, 2, 3).mockReset()

expect(fn(1, 2, 3)).toBeUndefined() // no mock for 1, 2, 3
expect(fn(2)).toEqual('boo!') // success!
```

#### Supports verifying that all mocked functions were called

Call `verifyAllWhenMocksCalled` after your test to assert that all mocks were used.
Expand Down
10 changes: 9 additions & 1 deletion src/when.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,15 @@ class WhenMock {
defaultImplementation: implementation => this.defaultImplementation(implementation),
defaultReturnValue: returnValue => this.defaultReturnValue(returnValue),
defaultResolvedValue: returnValue => this.defaultResolvedValue(returnValue),
defaultRejectedValue: err => this.defaultRejectedValue(err)
defaultRejectedValue: err => this.defaultRejectedValue(err),
mockReset: () => {
this.callMocks = this.callMocks
.filter((callMock) => !equals(callMock.matchers, matchers))
return {
...this,
...mockFunctions(matchers, expectCall)
}
}
})

// These four functions are only used when the dev has not used `.calledWith` before calling one of the mock return functions
Expand Down
55 changes: 55 additions & 0 deletions src/when.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1125,5 +1125,60 @@ describe('When', () => {
it('does not add to the number of assertion calls', () => {
expect.assertions(0)
})

it('allows reset of specific mock with specific args by just setting to undefined', () => {
const mock = jest.fn()

when(mock).calledWith('hello').mockReturnValue('default')
expect(mock.__whenMock__.callMocks).toHaveLength(1)
when(mock).calledWith('hello').mockReturnValue(undefined)
expect(mock.__whenMock__.callMocks).toHaveLength(1)
when(mock).calledWith('hello').mockReturnValueOnce('a')
expect(mock.__whenMock__.callMocks).toHaveLength(2)
when(mock).calledWith('hello').mockReturnValueOnce('b')
expect(mock.__whenMock__.callMocks).toHaveLength(3)

expect(mock('hello')).toEqual('a')
expect(mock('hello')).toEqual('b')
expect(mock('hello')).toEqual(undefined)

console.log(mock.__whenMock__.callMocks)

// There are still 3 when mocks, we just set the return value of the first one to undefined
expect(mock.__whenMock__.callMocks).toHaveLength(3)
})

it('allows reset of specific mock with specific args by using mockReset after calledWith', () => {
const mock = jest.fn()

when(mock).calledWith('hello').mockReturnValue('default')
expect(mock.__whenMock__.callMocks).toHaveLength(1)
when(mock).calledWith('hello').mockReset()
expect(mock.__whenMock__.callMocks).toHaveLength(0)
when(mock).calledWith('hello').mockReturnValueOnce('a')
expect(mock.__whenMock__.callMocks).toHaveLength(1)
when(mock).calledWith('hello').mockReturnValueOnce('b')
expect(mock.__whenMock__.callMocks).toHaveLength(2)

expect(mock('hello')).toEqual('a')
expect(mock('hello')).toEqual('b')
expect(mock('hello')).toEqual(undefined)

// The first one was removed so only 2 remain
expect(mock.__whenMock__.callMocks).toHaveLength(2)

//
// Try again with multiple matchers
const fn = jest.fn()

when(fn).calledWith(1, 2, 3).mockReturnValue('yay!')
when(fn).calledWith(2).mockReturnValue('boo!')

// Reset only the 1, 2, 3 mock call
when(fn).calledWith(1, 2, 3).mockReset()

expect(fn(1, 2, 3)).toBeUndefined() // no mock for 1, 2, 3
expect(fn(2)).toEqual('boo!') // success!
})
})
})

0 comments on commit ce60dd5

Please sign in to comment.