@moxyjs/moxy
v1.1.0
Published
Mock everything with Proxy
Downloads
59
Readme
Highlight
- One simple but powerful API
- Mock any
function
,object
andclass
- Mock methods
- Mock getters and setters
- Mock any property chain optionally
- Configurable & pluginable
Index: Install - Usage - API - Advanced Topic
Install
with npm:
npm install @moxyjs/moxy
or yarn:
yarn add @moxyjs/moxy
Use with Jest
Add the setup file in your jest config like:
module.exports = {
// ...
setupFiles: [
'<rootDir>/node_modules/@moxyjs/moxy/lib/extends/jest.js',
],
};
Usage
import { moxy } from '@moxyjs/moxy';
const spy = moxy(/* anything to mock */);
spy(); // an empty function by default
Mock a function
const hello = moxy(() => 'world');
hello('foo'); // 'world'
hello.mock.fake(() => 'bar')
hello('foo'); // 'bar'
hello.mock.fakeReturnValue('baz')
hello('foo'); // 'baz'
expect(hello).toHaveBeenCalledTimes(3);
expect(hello).toHaveBeenCalledWith('foo');
Fake once
const hello = moxy(() => 'world');
hello.mock.fakeReturnValue('foo');
hello.mock.fakeOnce(() => 'bar');
hello.mock.fakeReturnValueOnce('baz');
hello(); // 'bar'
hello(); // 'baz'
hello(); // 'foo'
Mock an object
const duck = moxy({
say: () => 'quack',
swim: true,
});
duck.say('foo'); // 'quack'
duck.swim; // true
duck.say.mock.fakeReturnValue('meow')
duck.say('foo'); // 'meow'
duck.mock.getter('swim').mockReturnValue(false)
duck.swim; // false
expect(duck.say.mock).toHaveBeenCalledWith('foo');
Mock a class
const Cat = moxy(class Cat {
say() {
return 'meow';
},
});
const cat = new Cat('orange');
cat.say('foo'); // 'meow'
// the instance is mocked
cat.say.mock.fakeReturnValue('purr');
cat.say('foo'); // 'purr'
// fake class implementation
Cat.mock.fakeReturnValue(class NyanCat {
say() {
return 'nyan~nyan~nyan~';
},
});
const cat2 = new Cat('rainbow');
cat2.say('foo'); // 'nyan~nyan~nyan~'
expect(Cat.mock).toHaveBeenCalledTimes(2);
expect(Cat.mock).toHaveBeenCalledWith('rainbow');
expect(cat.say.mock).toHaveBeenCalledTimes(3);
API
moxy(value, options)
Return the mocked value
- value -
object|function
, the obejct to be mocked, default tofunction(){}
. - options -
object
, the mock options, default to{}
accessKey
-string
, the key to accessMock
object, default to'mock'
mockReturn: true
-boolean
, whether to mock returned value, default tofalse
mockNewInstance
-boolean
, whether to mock constructing call, default totrue
,mockMethod
:boolean
, whether to mock methods, default totrue
,recordGetter
-boolean
, whether to record getter calls, default tofalse
,recordSetter
-boolean
, whether to record setter calls, default totrue
,middlewares
-function[]
, middleware functions, default tonull
,includeProperties
-(string|symbol)[]
, mock matched methods and properties, default tonull
excludeProperties
-(string|symbol)[]
, exclude matched methods and properties, default tonull
Mock
The mocking operator class
getCalls()
- return the functionCall
arraygetter(key)
- return the getterMock
of a propertysetter(key)
- return the setterMock
of a propertykey
-string|symbol
- the property name
fake(impl)
- fake function callfakeOnce(impl)
- fake function call onceimpl
-function
, the faked implementation
fakeReturnValue(value)
- fake returned valuefakeReturnValueOnce(value)
- fake returned valuevalue
-any
, the faked value
wrap(wrapFn)
- wrap function call behaviorwrapOnce(wrapFn)
- wrap function call behavior oncewrapFn
-(originalImpl) => fakedImpl
, receive the original implementation and return the faked one
proxify(source)
- return a mockedProxy
of the source which is controlled by itself
Call
A function call record
args
-any[]
, the function call augumentsresult
-any
, the returned value or the thrown error.instance
-any
, the bound object, i.e.this
isThrown
-boolean
, whether the call is thrownisConstructor
-boolean
, whether it's a constructing call withnew
isMoxy(value)
Check whether a value is moxied. Return a boolean
. For example:
import { moxy, isMoxy } from '@moxyjs/moxy';
isMoxy({}); // false
isMoxy(moxy()); // true
- value -
any
, the value to check
factory(options)
Create a moxy
function with new default options. For example:
import { factory } from '@moxyjs/moxy';
const moxy = factory({
recordGetter: true,
mockReturn: true,
});
const foo = moxy();
const bar = moxy();
- options -
object
, the same as options ofmoxy
Advanced Topic
Mock an object deeply
Any property chain matched by includeProperties
is mocked deeply. The property name is checked using micromatch
.
const obj = moxy(
{
foo: {
bar: {
baz: {
hello: () => 'world'
},
},
},
},
{ includeProperties: ['foo', 'b*'] },
);
obj.foo.bar.baz.hello(); // 'world'
obj.foo.bar.baz.hello.mock.fakeReturnValue('there');
obj.foo.bar.baz.hello(); // 'there'
Use one Mock
to mock many instances
This is useful to mock all instances of a class:
import { moxy, Mock, trackNewInstances } from '@moxyjs/moxy';
const fooMock = new Mock();
const Foo = moxy(
class Foo {
bar() {
return 'baz';
}
}
);
Foo.mock.wrap(trackNewInstances(fooMock));
new Foo().bar(); // 'baz'
fooMock.getter('bar').fakeReturnValue('zaq');
new Foo().bar(); // 'zaq'
Or to mock a curried function:
import { moxy, trackCurriedFunction } from '@moxyjs/moxy';
const curriedFn = moxy(
() => () => () => '🍛'
);
curriedFn.mock.wrap(trackCurriedFunction());
curriedFn('foo')('bar')('baz'); // '🍛'
expect(mock).toHaveBeenNthCalledWith(1, 'foo');
expect(mock).toHaveBeenNthCalledWith(2, 'bar');
expect(mock).toHaveBeenNthCalledWith(3, 'baz');
Proxy Handle Middleware
You can define the underlying proxy handler with the middlewares
option. For example:
const foo = moxy({ bar: 'baz' }, {
middlewares: [
(handler) => ({
...handler,
deleteProperty(target, prop) {
target[prop] = 'deleted';
},
})
],
});
delete foo.bar;
foo.bar; // 'deleted'