Allow users to create mocks using 2 APIs... Consumers or providors could write mocks using these tools...
// This block only runs if recording live
await ifLiveBlock(async () => {
await new Promise(resolve => {
const pipe = spawn("mongod", ["--dbpath=<LOCATION>", "--port", "1223"]);
pipe.stdout.on("data", function(data) {
if (data.indexOf("started") !== -1) {
resolve();
}
});
});
});
// if CLI flag / env var is set to record, this returns the live server results
// if not, it returns a snapshotted version. When live the above ifLiveBlock would have
// started the server it would connect to making the process seamless
const results = await memorized("Mocked query for bar", async () => {
const client = await mongodb.connect({ port: 1223 });
return client.query({ foo: "bar" });
});
// In the above call to memorizeMock we have a name, a function that conditionaly called
// if we are "recording" or the snapshotted response if playing back.
Pros:
- one test/mock file, and one step... No need to write a test that generates the mocks first, allowing it to feel a lot more like Jest snapshots.
- This not only allows for tests to be run as unit tests... but if the CI flag is on also as intigration tests. All with a single test being written!
- No setup to ensure is working localy or a CI... enviorment starting or not is not programaticly controlled in the test itself
That's the API... in practice it would look more like this:
///////////////////////
// user.test.js
///////////////////////
test("user creation works", () => {
const user = require("../user");
return user.create("mitchell", 22);
});
///////////////////////
// ./__mocks__/user.js
///////////////////////
const user = jest.genMockFromModule("../user");
// If the tests using this mock are live, this runs, otherwise it does not
await ifLiveBlock(async () => {
await new Promise(resolve => {
const pipe = spawn("mongod", ["--dbpath=<LOCATION>", "--port", "1223"]);
pipe.stdout.on("data", function(data) {
if (data.indexOf("started") !== -1) {
resolve();
}
});
});
});
// If live, this returns data from the live mongodb server,
// otherwise it returns from the memorized data saved to a snapshot
user.create = (name, age) => {
return await memorized(`create-user`,
async () => {
const mongodb = require('mongodb');
const client = await mongodb.connect({ port: 1223 });
return await client.insert({ name, age });
}, [...args]
// ˆˆ matches all args to the snapshot data
);
};
module.exports = user;
If memorized/ifLiveBlock use an env var to toggle live vs mocked data, then this becomes Test framework agnostic.
This API/setup also means I can make use of all the advantages of this regardless of if I am the providor OR the consumer of the mocks, meaning I don't need to get buy-in from the entire team or company to use it.
More or less, you have it. Your genMockFromModule call is incorrect, it needs to be called on ./user
Also your code is not doing the more powerful step of starting the dB process using ifLiveBlock. Being able to do so is what allows a single test to be both unit and integration depending on if it’s run love or not