diff --git a/doc/api/test.md b/doc/api/test.md index 76762c07c35..64a54923b74 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -2048,6 +2048,87 @@ added: Resets the implementation of the mock module. +## Class: `MockPropertyContext` + + + +The `MockPropertyContext` class is used to inspect or manipulate the behavior +of property mocks created via the [`MockTracker`][] APIs. + +### `ctx.accesses` + +* {Array} + +A getter that returns a copy of the internal array used to track accesses (get/set) to +the mocked property. Each entry in the array is an object with the following properties: + +* `type` {string} Either `'get'` or `'set'`, indicating the type of access. +* `value` {any} The value that was read (for `'get'`) or written (for `'set'`). +* `stack` {Error} An `Error` object whose stack can be used to determine the + callsite of the mocked function invocation. + +### `ctx.accessCount()` + +* Returns: {integer} The number of times that the property was accessed (read or written). + +This function returns the number of times that the property was accessed. +This function is more efficient than checking `ctx.accesses.length` because +`ctx.accesses` is a getter that creates a copy of the internal access tracking array. + +### `ctx.mockImplementation(value)` + +* `value` {any} The new value to be set as the mocked property value. + +This function is used to change the value returned by the mocked property getter. + +### `ctx.mockImplementationOnce(value[, onAccess])` + +* `value` {any} The value to be used as the mock's + implementation for the invocation number specified by `onAccess`. +* `onAccess` {integer} The invocation number that will use `value`. If + the specified invocation has already occurred then an exception is thrown. + **Default:** The number of the next invocation. + +This function is used to change the behavior of an existing mock for a single +invocation. Once invocation `onAccess` has occurred, the mock will revert to +whatever behavior it would have used had `mockImplementationOnce()` not been +called. + +The following example creates a mock function using `t.mock.property()`, calls the +mock property, changes the mock implementation to a different value for the +next invocation, and then resumes its previous behavior. + +```js +test('changes a mock behavior once', (t) => { + const obj = { foo: 1 }; + + const prop = t.mock.property(obj, 'foo', 5); + + assert.strictEqual(obj.foo, 5); + prop.mock.mockImplementationOnce(25); + assert.strictEqual(obj.foo, 25); + assert.strictEqual(obj.foo, 5); +}); +``` + +#### Caveat + +For consistency with the rest of the mocking API, this function treats both property gets and sets +as accesses. If a property set occurs at the same access index, the "once" value will be consumed +by the set operation, and the mocked property value will be changed to the "once" value. This may +lead to unexpected behavior if you intend the "once" value to only be used for a get operation. + +### `ctx.resetAccesses()` + +Resets the access history of the mocked property. + +### `ctx.restore()` + +Resets the implementation of the mock property to its original behavior. The +mock can still be used after calling this function. + ## Class: `MockTracker` + +* `object` {Object} The object whose value is being mocked. +* `propertyName` {string|symbol} The identifier of the property on `object` to mock. +* `value` {any} An optional value used as the mock value + for `object[propertyName]`. **Default:** The original property value. +* Returns: {Proxy} A proxy to the mocked object. The mocked object contains a + special `mock` property, which is an instance of [`MockPropertyContext`][], and + can be used for inspecting and changing the behavior of the mocked property. + +Creates a mock for a property value on an object. This allows you to track and control access to a specific property, +including how many times it is read (getter) or written (setter), and to restore the original value after mocking. + +```js +test('mocks a property value', (t) => { + const obj = { foo: 42 }; + const prop = t.mock.property(obj, 'foo', 100); + + assert.strictEqual(obj.foo, 100); + assert.strictEqual(prop.mock.accessCount(), 1); + assert.strictEqual(prop.mock.accesses[0].type, 'get'); + assert.strictEqual(prop.mock.accesses[0].value, 100); + + obj.foo = 200; + assert.strictEqual(prop.mock.accessCount(), 2); + assert.strictEqual(prop.mock.accesses[1].type, 'set'); + assert.strictEqual(prop.mock.accesses[1].value, 200); + + prop.mock.restore(); + assert.strictEqual(obj.foo, 42); +}); +``` + ### `mock.reset()`