javascript - Jest testing mongoose model instantiation -
i'm trying test rest api built express , mongoose, i'm using jest , supertest http calls; i'm relatively new testing javascript.
when testing creation url wan't make sure instantiation called using req.body object i'm not sure how it, after reading lot differences between mock objects , stubs , of jest documentation last try looks this:
test('should instantiate model using req.body', done => { const postmock = jest.fn(); const testpost = { name: 'test post', content: 'hello' }; postmock.bind(post); // <- post model // mock save function doesn't use db @ post.prototype.save = jest.fn(cb => cb(null, testpost)); // supertest call request(app).post('/posts/') .send(testpost) .then(() => { expect(postmock.mock.calls[0][0]).toequal(testpost); done(); }) .catch(err => {throw err}); });
also know how manually fail test on promise rejection, doesn't throws timeout - async callback not invoked within timeout specified jasmine.default_timeout_interval.
as stands, you're performing more of integration test rather isolating route handler function , testing that.
first break away handler /posts/
own file (assuming haven't done already):
controllers/post-controller.js
const post = require('./path/to/models/post') exports.store = async (req, res) => { const post = await new post(req.body).save() res.json({ data: post } }
next use handler wherever defined routes:
const express = require('express') const app = express() const postcontroller = require('./path/to/controllers/post-controller') app.post('/posts', postcontroller.store)
with abstraction can isolate our postcontroller.store
, test works req.body
. since need mock mongoose avoid hitting actual database, can create mocked post
(using code have):
path/to/models/__mocks__/post.js
const post = require('../post') const mockedpost = jest.fn() mockedpost.bind(post) const testpost = { name: 'test post', content: 'hello' } post.prototype.save = jest.fn(cb => { if (typeof cb === 'function') { if (process.env.force_fail === 'true') { process.nexttick(cb(new error(), null)) } else { process.nexttick(cb(null, testpost)) } } else { return new promise((resolve, reject) => { if (process.env.force_fail === 'true') { reject(new error()) } else { resolve(testpost) } }) } }) module.exports = mockedpost
notice check process.env.force_fail
if whatever reason wanted fail it.
now we're ready test using req.body
works:
post-controller.test.js
// loads contained in `models/__mocks__` folder jest.mock('../location/to/models') const postcontroller = require('../location/to/controllers/post-controller') describe('controllers.post', () => { /** * mocked express request object. */ let req /** * mocked express response object. */ let res beforeeach(() => { req = { body: {} } res = { data: null, json(payload) { this.data = json.stringify(payload) } } }) describe('.store()', () => { test('should create new post', async () => { req.body = { ... } await postcontroller(req, res) expect(res.data).tobedefined() ... }) test('fails creating post', () => { process.env.force_fail = true req.body = { ... } try { await postcontroller.store(req, res) } catch (error) { expect(res.data).not.tobedefined() ... } }) }) })
this code untested, hope helps in testing.
Comments
Post a Comment