Skip to content

Commit

Permalink
Add documentation related to auto-mocking (#8099)
Browse files Browse the repository at this point in the history
* add tests and documentation related to auto mocking

* add mock function language and link to the mock function docs

* fix string typo

* adjust language for string description

* line spacing and array property example

* update versioned docs and changelog

* fix following typo

* update language to consistently use present tense / update versioned docs

* update function names in test to match example code

* update wording of primitive description

* update wording of primitive description in code comment

* move auto-mocking changelog line under master heading

* move auto-mocking changelog line under master heading
  • Loading branch information
mackness authored and SimenB committed Mar 18, 2019
1 parent 76782b8 commit 90c6002
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 0 deletions.
2 changes: 2 additions & 0 deletions 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
Expand Down
93 changes: 93 additions & 0 deletions docs/JestObjectAPI.md
Expand Up @@ -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:
Expand Down
46 changes: 46 additions & 0 deletions packages/jest-mock/src/__tests__/index.test.ts
Expand Up @@ -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', () => {
Expand All @@ -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', () => {
Expand Down
93 changes: 93 additions & 0 deletions website/versioned_docs/version-22.x/JestObjectAPI.md
Expand Up @@ -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:
Expand Down
93 changes: 93 additions & 0 deletions website/versioned_docs/version-23.x/JestObjectAPI.md
Expand Up @@ -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:
Expand Down

0 comments on commit 90c6002

Please sign in to comment.