diff --git a/CHANGELOG.md b/CHANGELOG.md index 365621c5e1a0..d1718e470eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## master +- `[*]` Add documentation and tests related to auto-mocking ([#8086](https://github.com/facebook/jest/pull/8099)) + ### Features ### Fixes diff --git a/docs/JestObjectAPI.md b/docs/JestObjectAPI.md index 4b4fea15dfed..1a6cb5afe945 100644 --- a/docs/JestObjectAPI.md +++ b/docs/JestObjectAPI.md @@ -119,6 +119,99 @@ test('implementation created by jest.genMockFromModule', () => { }); ``` +This is how `genMockFromModule` will mock the following data types: + +#### `Function` + +Creates a new [mock function](https://jestjs.io/docs/en/mock-functions.html). The new function has no formal parameters and when called will return `undefined`. This functionality also applies to `async` functions. + +#### `Class` + +Creates new class. The interface of the original class is maintained, all of the class member functions and properties will be mocked. + +#### `Object` + +Creates a new deeply cloned object. The object keys are maintained and their values are mocked. + +#### `Array` + +Creates a new empty array, ignoring the original. + +#### `Primitives` + +Creates a new property with the same primitive value as the original property. + +Example: + +``` +// example.js +module.exports = { + function: function square(a, b) { + return a * b; + }, + asyncFunction: async function asyncSquare(a, b) { + const result = await a * b; + return result; + }, + class: new class Bar { + constructor() { + this.array = [1, 2, 3]; + } + foo() {} + }, + object: { + baz: 'foo', + bar: { + fiz: 1, + buzz: [1, 2, 3], + }, + }, + array: [1, 2, 3], + number: 123, + string: 'baz', + boolean: true, + symbol: Symbol.for('a.b.c'), +}; +``` + +```js +// __tests__/example.test.js +const example = jest.genMockFromModule('./example'); + +test('should run example code', () => { + // creates a new mocked function with no formal arguments. + expect(example.function.name).toEqual('square'); + expect(example.function.length).toEqual(0); + + // async functions get the same treatment as standard synchronous functions. + expect(example.asyncFunction.name).toEqual('asyncSquare'); + expect(example.asyncFunction.length).toEqual(0); + + // creates a new class with the same interface, member functions and properties are mocked. + expect(example.class.constructor.name).toEqual('Bar'); + expect(example.class.foo.name).toEqual('foo'); + expect(example.class.array.length).toEqual(0); + + // creates a deeply cloned version of the original object. + expect(example.object).toEqual({ + baz: 'foo', + bar: { + fiz: 1, + buzz: [], + }, + }); + + // creates a new empty array, ignoring the original array. + expect(example.array.length).toEqual(0); + + // creates a new property with the same primitive value as the original property. + expect(example.number).toEqual(123); + expect(example.string).toEqual('baz'); + expect(example.boolean).toEqual(true); + expect(example.symbol).toEqual(Symbol.for('a.b.c')); +}); +``` + ### `jest.mock(moduleName, factory, options)` Mocks a module with an auto-mocked version when it is being required. `factory` and `options` are optional. For example: diff --git a/packages/jest-mock/src/__tests__/index.test.ts b/packages/jest-mock/src/__tests__/index.test.ts index bd0d57f50746..64c47464be83 100644 --- a/packages/jest-mock/src/__tests__/index.test.ts +++ b/packages/jest-mock/src/__tests__/index.test.ts @@ -34,6 +34,7 @@ describe('moduleMocker', () => { expect(moduleMocker.getMetadata('banana').value).toEqual('banana'); expect(moduleMocker.getMetadata(27).value).toEqual(27); expect(moduleMocker.getMetadata(false).value).toEqual(false); + expect(moduleMocker.getMetadata(Infinity).value).toEqual(Infinity); }); it('does not retrieve metadata for arrays', () => { @@ -57,6 +58,51 @@ describe('moduleMocker', () => { expect(metadata.members).toBeUndefined(); expect(metadata.type).toEqual('null'); }); + + it('retrieves metadata for ES6 classes', () => { + class ClassFooMock { + bar() {} + } + const fooInstance = new ClassFooMock(); + const metadata = moduleMocker.getMetadata(fooInstance); + expect(metadata.type).toEqual('object'); + expect(metadata.members.constructor.name).toEqual('ClassFooMock'); + }); + + it('retrieves synchronous function metadata', () => { + function functionFooMock() {} + const metadata = moduleMocker.getMetadata(functionFooMock); + expect(metadata.type).toEqual('function'); + expect(metadata.name).toEqual('functionFooMock'); + }); + + it('retrieves asynchronous function metadata', () => { + async function asyncFunctionFooMock() {} + const metadata = moduleMocker.getMetadata(asyncFunctionFooMock); + expect(metadata.type).toEqual('function'); + expect(metadata.name).toEqual('asyncFunctionFooMock'); + }); + + it("retrieves metadata for object literals and it's members", () => { + const metadata = moduleMocker.getMetadata({ + bar: 'two', + foo: 1, + }); + expect(metadata.type).toEqual('object'); + expect(metadata.members.bar.value).toEqual('two'); + expect(metadata.members.bar.type).toEqual('constant'); + expect(metadata.members.foo.value).toEqual(1); + expect(metadata.members.foo.type).toEqual('constant'); + }); + + it('retrieves Date object metadata', () => { + const metadata = moduleMocker.getMetadata(Date); + expect(metadata.type).toEqual('function'); + expect(metadata.name).toEqual('Date'); + expect(metadata.members.now.name).toEqual('now'); + expect(metadata.members.parse.name).toEqual('parse'); + expect(metadata.members.UTC.name).toEqual('UTC'); + }); }); describe('generateFromMetadata', () => { diff --git a/website/versioned_docs/version-22.x/JestObjectAPI.md b/website/versioned_docs/version-22.x/JestObjectAPI.md index 4fda2af835ba..9d57aab4562d 100644 --- a/website/versioned_docs/version-22.x/JestObjectAPI.md +++ b/website/versioned_docs/version-22.x/JestObjectAPI.md @@ -173,6 +173,99 @@ test('implementation created by jest.genMockFromModule', () => { }); ``` +This is how `genMockFromModule` will mock the following data types: + +#### `Function` + +Creates a new [mock function](https://jestjs.io/docs/en/mock-functions.html). The new function has no formal parameters and when called will return `undefined`. This functionality also applies to `async` functions. + +#### `Class` + +Creates new class. The interface of the original class is maintained, all of the class member functions and properties will be mocked. + +#### `Object` + +Creates a new deeply cloned object. The object keys are maintained and their values are mocked. + +#### `Array` + +Creates a new empty array, ignoring the original. + +#### `Primitives` + +Creates a new property with the same primitive value as the original property. + +Example: + +``` +// example.js +module.exports = { + function: function square(a, b) { + return a * b; + }, + asyncFunction: async function asyncSquare(a, b) { + const result = await a * b; + return result; + }, + class: new class Bar { + constructor() { + this.array = [1, 2, 3]; + } + foo() {} + }, + object: { + baz: 'foo', + bar: { + fiz: 1, + buzz: [1, 2, 3], + }, + }, + array: [1, 2, 3], + number: 123, + string: 'baz', + boolean: true, + symbol: Symbol.for('a.b.c'), +}; +``` + +```js +// __tests__/example.test.js +const example = jest.genMockFromModule('./example'); + +test('should run example code', () => { + // creates a new mocked function with no formal arguments. + expect(example.function.name).toEqual('square'); + expect(example.function.length).toEqual(0); + + // async functions get the same treatment as standard synchronous functions. + expect(example.asyncFunction.name).toEqual('asyncSquare'); + expect(example.asyncFunction.length).toEqual(0); + + // creates a new class with the same interface, member functions and properties are mocked. + expect(example.class.constructor.name).toEqual('Bar'); + expect(example.class.foo.name).toEqual('foo'); + expect(example.class.array.length).toEqual(0); + + // creates a deeply cloned version of the original object. + expect(example.object).toEqual({ + baz: 'foo', + bar: { + fiz: 1, + buzz: [], + }, + }); + + // creates a new empty array, ignoring the original array. + expect(example.array.length).toEqual(0); + + // creates a new property with the same primitive value as the original property. + expect(example.number).toEqual(123); + expect(example.string).toEqual('baz'); + expect(example.boolean).toEqual(true); + expect(example.symbol).toEqual(Symbol.for('a.b.c')); +}); +``` + ### `jest.mock(moduleName, factory, options)` Mocks a module with an auto-mocked version when it is being required. `factory` and `options` are optional. For example: diff --git a/website/versioned_docs/version-23.x/JestObjectAPI.md b/website/versioned_docs/version-23.x/JestObjectAPI.md index e14aaaa58717..a32bac460849 100644 --- a/website/versioned_docs/version-23.x/JestObjectAPI.md +++ b/website/versioned_docs/version-23.x/JestObjectAPI.md @@ -174,6 +174,99 @@ test('implementation created by jest.genMockFromModule', () => { }); ``` +This is how `genMockFromModule` will mock the following data types: + +#### `Function` + +Creates a new [mock function](https://jestjs.io/docs/en/mock-functions.html). The new function has no formal parameters and when called will return `undefined`. This functionality also applies to `async` functions. + +#### `Class` + +Creates new class. The interface of the original class is maintained, all of the class member functions and properties will be mocked. + +#### `Object` + +Creates a new deeply cloned object. The object keys are maintained and their values are mocked. + +#### `Array` + +Creates a new empty array, ignoring the original. + +#### `Primitives` + +Creates a new property with the same primitive value as the original property. + +Example: + +``` +// example.js +module.exports = { + function: function square(a, b) { + return a * b; + }, + asyncFunction: async function asyncSquare(a, b) { + const result = await a * b; + return result; + }, + class: new class Bar { + constructor() { + this.array = [1, 2, 3]; + } + foo() {} + }, + object: { + baz: 'foo', + bar: { + fiz: 1, + buzz: [1, 2, 3], + }, + }, + array: [1, 2, 3], + number: 123, + string: 'baz', + boolean: true, + symbol: Symbol.for('a.b.c'), +}; +``` + +```js +// __tests__/example.test.js +const example = jest.genMockFromModule('./example'); + +test('should run example code', () => { + // creates a new mocked function with no formal arguments. + expect(example.function.name).toEqual('square'); + expect(example.function.length).toEqual(0); + + // async functions get the same treatment as standard synchronous functions. + expect(example.asyncFunction.name).toEqual('asyncSquare'); + expect(example.asyncFunction.length).toEqual(0); + + // creates a new class with the same interface, member functions and properties are mocked. + expect(example.class.constructor.name).toEqual('Bar'); + expect(example.class.foo.name).toEqual('foo'); + expect(example.class.array.length).toEqual(0); + + // creates a deeply cloned version of the original object. + expect(example.object).toEqual({ + baz: 'foo', + bar: { + fiz: 1, + buzz: [], + }, + }); + + // creates a new empty array, ignoring the original array. + expect(example.array.length).toEqual(0); + + // creates a new property with the same primitive value as the original property. + expect(example.number).toEqual(123); + expect(example.string).toEqual('baz'); + expect(example.boolean).toEqual(true); + expect(example.symbol).toEqual(Symbol.for('a.b.c')); +}); +``` + ### `jest.mock(moduleName, factory, options)` Mocks a module with an auto-mocked version when it is being required. `factory` and `options` are optional. For example: diff --git a/website/versioned_docs/version-24.0/JestObjectAPI.md b/website/versioned_docs/version-24.0/JestObjectAPI.md index 3ab253e66d6a..ca754af8600e 100644 --- a/website/versioned_docs/version-24.0/JestObjectAPI.md +++ b/website/versioned_docs/version-24.0/JestObjectAPI.md @@ -120,6 +120,99 @@ test('implementation created by jest.genMockFromModule', () => { }); ``` +This is how `genMockFromModule` will mock the following data types: + +#### `Function` + +Creates a new [mock function](https://jestjs.io/docs/en/mock-functions.html). The new function has no formal parameters and when called will return `undefined`. This functionality also applies to `async` functions. + +#### `Class` + +Creates new class. The interface of the original class is maintained, all of the class member functions and properties will be mocked. + +#### `Object` + +Creates a new deeply cloned object. The object keys are maintained and their values are mocked. + +#### `Array` + +Creates a new empty array, ignoring the original. + +#### `Primitives` + +Creates a new property with the same primitive value as the original property. + +Example: + +``` +// example.js +module.exports = { + function: function square(a, b) { + return a * b; + }, + asyncFunction: async function asyncSquare(a, b) { + const result = await a * b; + return result; + }, + class: new class Bar { + constructor() { + this.array = [1, 2, 3]; + } + foo() {} + }, + object: { + baz: 'foo', + bar: { + fiz: 1, + buzz: [1, 2, 3], + }, + }, + array: [1, 2, 3], + number: 123, + string: 'baz', + boolean: true, + symbol: Symbol.for('a.b.c'), +}; +``` + +```js +// __tests__/example.test.js +const example = jest.genMockFromModule('./example'); + +test('should run example code', () => { + // creates a new mocked function with no formal arguments. + expect(example.function.name).toEqual('square'); + expect(example.function.length).toEqual(0); + + // async functions get the same treatment as standard synchronous functions. + expect(example.asyncFunction.name).toEqual('asyncSquare'); + expect(example.asyncFunction.length).toEqual(0); + + // creates a new class with the same interface, member functions and properties are mocked. + expect(example.class.constructor.name).toEqual('Bar'); + expect(example.class.foo.name).toEqual('foo'); + expect(example.class.array.length).toEqual(0); + + // creates a deeply cloned version of the original object. + expect(example.object).toEqual({ + baz: 'foo', + bar: { + fiz: 1, + buzz: [], + }, + }); + + // creates a new empty array, ignoring the original array. + expect(example.array.length).toEqual(0); + + // creates a new property with the same primitive value as the original property. + expect(example.number).toEqual(123); + expect(example.string).toEqual('baz'); + expect(example.boolean).toEqual(true); + expect(example.symbol).toEqual(Symbol.for('a.b.c')); +}); +``` + ### `jest.mock(moduleName, factory, options)` Mocks a module with an auto-mocked version when it is being required. `factory` and `options` are optional. For example: