forked from vitest-dev/vitest
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(vitest): independently mock each instance's methods for mocked cl…
…ass (vitest-dev#4564)
- Loading branch information
1 parent
8184f78
commit da03b91
Showing
5 changed files
with
317 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export const symbolFn = Symbol.for('symbolFn') | ||
|
||
export class MockedE { | ||
public testFn(arg: string) { | ||
return arg.repeat(2) | ||
} | ||
|
||
public [symbolFn](arg: string) { | ||
return arg.repeat(2) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { expect, test, vi } from 'vitest' | ||
|
||
import { MockedE } from '../src/mockedE' | ||
|
||
vi.mock('../src/mockedE') | ||
|
||
test(`mocked class are not affected by restoreAllMocks`, () => { | ||
const instance0 = new MockedE() | ||
expect(instance0.testFn('a')).toMatchInlineSnapshot(`undefined`) | ||
expect(vi.mocked(instance0.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
|
||
vi.restoreAllMocks() | ||
|
||
// reset only history after restoreAllMocks | ||
expect(instance0.testFn('b')).toMatchInlineSnapshot(`undefined`) | ||
expect(vi.mocked(instance0.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
|
||
// mocked constructor is still effective after restoreAllMocks | ||
const instance1 = new MockedE() | ||
const instance2 = new MockedE() | ||
expect(instance1).not.toBe(instance2) | ||
expect(instance1.testFn).not.toBe(instance2.testFn) | ||
expect(instance1.testFn).not.toBe(MockedE.prototype.testFn) | ||
expect(vi.mocked(instance1.testFn).mock).not.toBe(vi.mocked(instance2.testFn).mock) | ||
|
||
expect(instance1.testFn('c')).toMatchInlineSnapshot(`undefined`) | ||
expect(vi.mocked(instance0.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"c", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(instance2.testFn).mock.calls).toMatchInlineSnapshot(`[]`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
[ | ||
"c", | ||
], | ||
] | ||
`) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { expect, test, vi } from 'vitest' | ||
|
||
import { MockedE } from '../src/mockedE' | ||
|
||
vi.mock('../src/mockedE') | ||
|
||
// this behavior looks odd but jest also doesn't seem to support this use case properly | ||
test(`mocked class methods are not restorable by explicit mockRestore calls`, () => { | ||
const instance1 = new MockedE() | ||
|
||
expect(instance1.testFn('a')).toMatchInlineSnapshot(`undefined`) | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
|
||
// restoring instance method | ||
vi.mocked(instance1.testFn).mockRestore() | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(`[]`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
|
||
expect(instance1.testFn('b')).toMatchInlineSnapshot(`undefined`) | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
|
||
// restoring prototype method | ||
vi.mocked(MockedE.prototype.testFn).mockRestore() | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(`[]`) | ||
|
||
expect(instance1.testFn('c')).toMatchInlineSnapshot(`undefined`) | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
[ | ||
"c", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"c", | ||
], | ||
] | ||
`) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { expect, test, vi } from 'vitest' | ||
|
||
import { MockedE, symbolFn } from '../src/mockedE' | ||
|
||
vi.mock('../src/mockedE') | ||
|
||
test(`each instance's methods of mocked class should have independent mock function state`, () => { | ||
const instance1 = new MockedE() | ||
const instance2 = new MockedE() | ||
expect(instance1).not.toBe(instance2) | ||
expect(instance1.testFn).not.toBe(instance2.testFn) | ||
expect(instance1.testFn).not.toBe(MockedE.prototype.testFn) | ||
expect(vi.mocked(instance1.testFn).mock).not.toBe(vi.mocked(instance2.testFn).mock) | ||
|
||
expect(instance1.testFn('a')).toMatchInlineSnapshot(`undefined`) | ||
expect(instance1.testFn).toBeCalledTimes(1) | ||
expect(instance2.testFn).toBeCalledTimes(0) | ||
expect(MockedE.prototype.testFn).toBeCalledTimes(1) | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
] | ||
`) | ||
|
||
expect(instance2.testFn('b')).toMatchInlineSnapshot(`undefined`) | ||
expect(instance1.testFn).toBeCalledTimes(1) | ||
expect(instance2.testFn).toBeCalledTimes(1) | ||
expect(MockedE.prototype.testFn).toBeCalledTimes(2) | ||
expect(vi.mocked(instance2.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
|
||
expect(instance1.testFn('c')).toMatchInlineSnapshot(`undefined`) | ||
expect(instance1.testFn).toBeCalledTimes(2) | ||
expect(instance2.testFn).toBeCalledTimes(1) | ||
expect(MockedE.prototype.testFn).toBeCalledTimes(3) | ||
expect(vi.mocked(instance1.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
[ | ||
"c", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(instance2.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"b", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(MockedE.prototype.testFn).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"a", | ||
], | ||
[ | ||
"b", | ||
], | ||
[ | ||
"c", | ||
], | ||
] | ||
`) | ||
|
||
// test same things for symbol key method | ||
expect(instance1[symbolFn]).not.toBe(instance2[symbolFn]) | ||
expect(instance1[symbolFn]).not.toBe(MockedE.prototype[symbolFn]) | ||
expect(vi.mocked(instance1[symbolFn]).mock).not.toBe(vi.mocked(instance2[symbolFn]).mock) | ||
|
||
expect(instance1[symbolFn]('d')).toMatchInlineSnapshot(`undefined`) | ||
expect(instance1[symbolFn]).toBeCalledTimes(1) | ||
expect(instance2[symbolFn]).toBeCalledTimes(0) | ||
expect(MockedE.prototype[symbolFn]).toBeCalledTimes(1) | ||
expect(vi.mocked(instance1[symbolFn]).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"d", | ||
], | ||
] | ||
`) | ||
expect(vi.mocked(instance2[symbolFn]).mock.calls).toMatchInlineSnapshot(`[]`) | ||
expect(vi.mocked(MockedE.prototype[symbolFn]).mock.calls).toMatchInlineSnapshot(` | ||
[ | ||
[ | ||
"d", | ||
], | ||
] | ||
`) | ||
}) |