Skip to content

Commit cf560d4

Browse files
authored
feat(nested mock): expand PR 884 with tests (#1075)
1 parent 87df015 commit cf560d4

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

packages/testing/ts-jest/src/mocks.spec.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,28 @@ interface TestInterface {
1010
func: (num: number, str: string) => boolean;
1111
func2: (entity: TestClass) => void;
1212
func3: () => Promise<{ prop: number }>;
13+
nested: {
14+
someOtherNum: number;
15+
func4: () => boolean;
16+
};
1317
}
1418

1519
class TestClass {
1620
someProperty!: number;
1721

22+
nested = new NestedTestClass();
23+
1824
someMethod() {
1925
return 42;
2026
}
2127
}
2228

29+
class NestedTestClass {
30+
someOtherMethod() {
31+
return 24;
32+
}
33+
}
34+
2335
describe('Mocks', () => {
2436
const request = {
2537
headers: {
@@ -200,6 +212,22 @@ describe('Mocks', () => {
200212
expect(serviceMock.foo()).toEqual(false);
201213
expect(serviceMock.foo()).toEqual(true);
202214
});
215+
216+
it('should work with nested properties and functions', () => {
217+
const mock = createMock<TestInterface>();
218+
mock.nested.someOtherNum = 99;
219+
mock.nested.func4.mockReturnValueOnce(true);
220+
const result = mock.nested.func4();
221+
expect(mock.nested.someOtherNum).toBe(99);
222+
expect(result).toBe(true);
223+
});
224+
225+
it('should work with classes having nested properties', () => {
226+
const mock = createMock<TestClass>();
227+
mock.nested.someOtherMethod.mockReturnValueOnce(99);
228+
const result = mock.nested.someOtherMethod();
229+
expect(result).toBe(99);
230+
});
203231
});
204232

205233
describe('auto mocked', () => {
@@ -360,7 +388,9 @@ describe('Mocks', () => {
360388
it('should throw error when calling unstubbed method in strict mode', () => {
361389
const mock = createMock<TestInterface>({}, { strict: true });
362390

363-
expect(() => mock.func(1, 'test')).toThrow('Method mock.func was called without being explicitly stubbed');
391+
expect(() => mock.func(1, 'test')).toThrow(
392+
'Method mock.func was called without being explicitly stubbed',
393+
);
364394

365395
mock.func.mockReturnValue(true);
366396
expect(mock.func(1, 'test')).toBe(true);

packages/testing/ts-jest/src/mocks.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export type DeepMocked<T> = {
2121
[K in keyof T]: Required<T>[K] extends (...args: any[]) => infer U
2222
? jest.MockInstance<ReturnType<Required<T>[K]>, jest.ArgsType<T[K]>> &
2323
((...args: jest.ArgsType<T[K]>) => DeepMocked<U>)
24-
: T[K];
24+
: DeepMocked<T[K]>;
2525
} & T;
2626

2727
const jestFnProps = new Set([
@@ -49,7 +49,11 @@ const jestFnProps = new Set([
4949
const createProxy: {
5050
<T extends object>(name: string, strict: boolean, base: T): T;
5151
<T extends Mock<any, any> = Mock<any, any>>(name: string, strict: boolean): T;
52-
} = <T extends object | Mock<any, any>>(name: string, strict: boolean, base?: T): T => {
52+
} = <T extends object | Mock<any, any>>(
53+
name: string,
54+
strict: boolean,
55+
base?: T,
56+
): T => {
5357
const cache = new Map<string | number | symbol, any>();
5458
const handler: ProxyHandler<T> = {
5559
get: (obj, prop, receiver) => {
@@ -105,7 +109,9 @@ const createProxy: {
105109
return result;
106110
} else {
107111
if (strict) {
108-
throw new Error(`Method ${name} was called without being explicitly stubbed`);
112+
throw new Error(
113+
`Method ${name} was called without being explicitly stubbed`,
114+
);
109115
}
110116
if (!cache.has('__apply')) {
111117
cache.set('__apply', createProxy(name, strict));

0 commit comments

Comments
 (0)