0

I am running into an issue trying to write a test. I got the following endpoint for a REST-API:

Post is a Mongoose model.

router.post('/addPost', (req, res) => {
  const post = new Post(req.body);
  post.save()
    .then(() => ... return success)
    .catch((err) => ... return error);
});

I would like to write a test to check if an the correct value is returned to the user when save() resolves.

I tried to mock the save() method in the model but this does not seem possible. As described here https://stackoverflow.com/a/34666488/10754437, save is not a method on the model, it's a method on the document (instance of a model).

I tried testing it as described in that post but I must be going at it the wrong way as I still can't manage to overwrite the save() method correctly.

I currently have this code (factory comes from factory-girl as described in the link I tried to use to solve this issue. Here is a direct link to the package):

factory.define('Post', Post, {
  save: new Promise((resolve, reject) => {
    resolve();
  }),
});
factory.build('Post').then((factoryPost) => {
  Post = factoryPost;
  PostMock = sinon.mock(Post);
  PostMock.expects('save').resolves({});

  ... perform test
});

I am guessing I am doing this horribly wrong but I cannot figure out what I am missing. I am guessing someone must have ran into this before.

Lin Du
  • 88,126
  • 95
  • 281
  • 483
SomeDutchGuy
  • 2,249
  • 4
  • 16
  • 42

1 Answers1

0

You can make stub for post document which is an instance of Post model by stub the Post.prototype.

E.g.

server.ts:

import express from 'express';
import Post from './models/post';
import http from 'http';

const app = express();
app.post('/addPost', async (req, res) => {
  const post = new Post(req.body);
  await post.save();
  res.sendStatus(200);
});

const server = http.createServer(app).listen(3000, () => {
  console.info('Http server is listening on http://localhost:3000');
});

export { server };

models/post.ts:

import { model, Schema } from 'mongoose';

const postSchema = new Schema({
  titie: String,
});

export default model('post', postSchema);

server.integration.spec.ts:

import { server } from './server';
import request from 'supertest';
import Post from './models/post';
import sinon from 'sinon';
import { expect } from 'chai';

after((done) => {
  server.close(done);
});

describe('58820254', () => {
  it('/addPost', (done) => {
    const saveStub = sinon.stub(Post.prototype, 'save').returnsThis();
    request(server)
      .post('/addPost')
      .expect(() => {
        console.log('assert');
        expect(saveStub.calledOnce).to.be.true;
      })
      .expect(200, done);
  });
});

Integration test with 100% coverage:

Http server is listening on http://localhost:3000
  58820254
assert
    ✓ /addPost


  1 passing (25ms)

-----------------------------|----------|----------|----------|----------|-------------------|
File                         |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------------------|----------|----------|----------|----------|-------------------|
All files                    |      100 |      100 |      100 |      100 |                   |
 58820254                    |      100 |      100 |      100 |      100 |                   |
  server.integration.spec.ts |      100 |      100 |      100 |      100 |                   |
  server.ts                  |      100 |      100 |      100 |      100 |                   |
 58820254/models             |      100 |      100 |      100 |      100 |                   |
  post.ts                    |      100 |      100 |      100 |      100 |                   |
-----------------------------|----------|----------|----------|----------|-------------------|

Source code: https://github.com/mrdulin/mongoose5.x-lab/tree/master/src/stackoverflow/58820254

Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • I will try this in a few day's. Currently my focus is on an other element of the project. If this works I will mark it as the answer soon as I have some time to implement it. – SomeDutchGuy Nov 18 '19 at 13:09