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

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -