parse-server-mocker
v1.2.3
Published
Easily mock Parse Server for efficient testing.
Downloads
61
Maintainers
Readme
parse-server-mocker
Easily mock Parse Server for efficient testing.
How does it work ?
parse-server-mocker simply override methods from global Parse, allowing to substitute the return value of these. Thus, you can provide any data you need for your tests without any instance of ParseServer running and slowing down your system.
Compatibility
parse-server-mocker is actively tested with Jest on NodeJS and TypeScript but should be compatible with all systems using ES6 or CommonJS.
Demo
This workspace contains 2 simples demo projects : the first one "demo-app" is based on Angular (Typescript/ES6), whereas the second one "demo-api" is built for NodeJS (CommonJS).
Both of them use a Parse Server instance in a standard way (localhost:1337). You can use your own or launch one with the docker compose file using
docker-compose up
.
In order to launch the tests suites, use
nx test demo-app
and nx test demo-api
.
Usage
Initialization
Before using parse-server-mocker in your test scripts, you need to initialize it first using mockParse(Parse);
(don't forget the import statement import * as Parse from 'parse';
).
This instruction must be called before any mock operation or you will run into undefined issues. Using Jest, a common usage is to place this in your "setupFilesAfterEnv" file (see "apps/demo-app/src/test-setup.ts" of the demo workspace).
Using NodeJs, depending on your configuration, you might have to add global.Parse = Parse;
to correctly replace the global instance.
Queries : get, find, first and findAll (and similars)
In order to provide your own data as the result of any query, you just need to feed parse-server-mocker mockedQuery with your own function :
ParseMock.instance.mockedQueryFirst = () => {
return Promise.resolve(word2);
}
ParseMock.instance.mockedQueryGet = () => Promise.resolve(undefined);
ParseMock.instance.mockedQueryFindAll = () => Promise.resolve([new Parse.Object()]);
You can also adapt the returned data according the Parse's original query automatically :
ParseMock.instance.mockedQueryGet = async query => {
if (query.className === 'WordDefinitionSuggestion') {
return new WordDefinitionSuggestion();
} else {
return undefined;
}
}
Saving object
Any Parse Object being saved is automatically handled by parse-server-mocker, so no need to perform any action. However, as part of your unit test, it may be necessary to check wich object has been was intercepted during the execution the service begin tested. This can be achieve using ParseMock.instance.history
:
// Adding random data
await service.addData();
// Adding specific data
await service.addData('The Evil That Men Do');
// Checking the history
expect(ParseMock.instance.history.length).toBe(2);
const hist1 = ParseMock.instance.history[0];
expect(hist1.method).toBe('save');
expect(hist1.source.get('label')).not.toBe('The Evil That Men Do');
const hist2 = ParseMock.instance.history[1];
expect(hist2.method).toBe('save');
expect(hist2.source.get('label')).toBe('The Evil That Men Do');
User management
The User management functions of Parse "logIn", "logOut", "become" and "current" are easy to rip off : they just all make use of the user you put in the ParseMock.instance.mockedUser
variable.
const user = new Parse.User();
user.setUsername('Buckethead');
ParseMock.instance.mockedUser = user;
After that, any "login()" call will have no effect and return the Buckethead user.
Parse Config
Mocking Parse Config is similar as mocking Parse queries except that that you provide directly the config object you want to be used :
it('fetchDisplayableServerInfo', async () => {
const config = {
bddVersion: '0.0.1'
};
ParseMock.instance.mockedCloudConfig = config;
const info = await service.fetchDisplayableServerInfo();
expect(info.indexOf('Running prod v0.0.1')).toBeGreaterThan(-1);
});
Here, the "fetchDisplayableServerInfo" method will use the Parse Config to get the BDD version and format the string to be returned.
Cloud functions
Cloud function calls can be mocked too using the system of function replacement. Here's an example :
// Simple
ParseMock.instance.mockedCloudRun = async () => {
return Promise.resolve(['Here is', 'some', 'fresh', 'data !']);
}
// Using call arguments
ParseMock.instance.mockedCloudRun = async (methodName, data, runOptions) => {
if (methodName === 'giveMeData') {
if (runOptions.useMasterKey) {
return Promise.resolve(['Here is', 'some', 'fresh', 'data !']);
} else {
return undefined;
}
} else {
console.log('Another thing, just saving something to BDD for example...');
}
}
Others functionalities
As you can see, many functionnalities work the same way. Not all of them will therefore be described in this documentation, but you should find them easily using the autocompletion of your IDE :
- query find
- query count
- query each
- object pin/unPin
- cloud triggers (beforeFind, beforeSave, afterSave, beforeDelete...)
- and more...
Way to go
I know many feature are still missing, I will implement them as time goes by, do not hesitate to contact me to suggest an improvement :)
Troubleshooting
"Undefined issues" ?
TypeError: Cannot set properties of undefined (setting 'mockedQueryFindAll')
Oh oh ! You forgot the initialization part (with mockParse(Parse);
), don't you ?
Or maybe you did not place it before your tests suites.
ReferenceError: Parse is not defined
Using NodeJS, you should add global.Parse = Parse;
after the mockParse(Parse);
instruction. Here's a sample Jest initialization file :
import * as Parse from 'parse';
import { mockParse } from 'parse-server-mocker';
mockParse(Parse);
global.Parse = Parse;
"Using Parse with IndexedDB ?"
As Jest doesn't provide IndexedDB natively, you should consider using "fake-indexeddb".
So you juste might have to require it in your initialization part (in your "test-setup.ts" for example) :
require("fake-indexeddb/auto");
License
MIT