Testing the Mongoose save() method by mocking it in an integration test

I am currently facing an issue while trying to create a test scenario. The problem arises with the endpoint I have for a REST-API:

Post represents a Mongoose model.

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

My goal is to write a test that verifies if the correct value is returned when save() resolves.

After attempting to mock the save() method within the model, I realized it may not be possible. As mentioned in this thread , save is not a method on the model itself but on the document (an instance of the model).

Even after following the recommended approach from the above-mentioned discussion, I seem to be missing something as I cannot successfully override the save() method.

The code snippet I have so far (factory is sourced from factory-girl as per the instructions provided in the given link. 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 believe my implementation might be off track, but I am unable to pinpoint where I am going wrong. There must be others who have encountered a similar issue before.

Answer №1

If you want to create a stub for the post document, which represents an instance of the Post model, you can achieve this by stubbing the Post.prototype.

For example:

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 full 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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a better method to determine the width when utilizing the jQuery UI resizable feature for improved efficiency?

I'm currently working on a website that features a resizable sidebar. I want the icons and text within the sidebar to shrink proportionally when the user resizes it. Right now, I have implemented an if statement to check if the sidebar's width fa ...

Data binding functions properly only when utilizing the syntax within the select ng-options

In the book AngularJS in Action, I came across this Angular controller: angular.module('Angello.Storyboard') .controller('StoryboardCtrl', function() { var storyboard = this; storyboard.currentStory = null; ...

Is there a way to make divs expand on top of existing content when hovering over them, in order to avoid needing to scroll through overflow content? I am currently working with

I am working with 9 boxes contained within divs, each box includes data that exceeds the size of the box itself (represented by Some Text repeated for demonstration purposes). I am seeking a solution where hovering over any box will cause it to enlarge and ...

What is the best way to open the index.html file in electron?

I'm currently developing a cross-platform app using electron and Angular. As of now, the code I have for loading my index.html file looks like this: exports.window = function window() { this.createWindow = (theBrowserWindow) => { // Create ...

leveraging the situation and a clever opening

Currently, I'm diving into mastering the proper utilization of context and hooks. Initially, everything worked flawlessly while all components remained within a single class. However, troubles arose when I segregated them into multiple classes leading ...

Error: Google Plus Cross-Origin Resource Sharing Issue

I recently developed an AngularJS application that utilizes Google's server-side flow for authentication. The issue arises when my AngularJS app is hosted on one server and the Rest API is hosted on another. After successfully logging in, I encounter ...

Prevent links from being clicked multiple times in Rails using Coffeescript

Please make the following link inactive after it has been clicked once <%= link_to "Submit Order", {:action => "charge"}, class: 'btn btn-primary', id: 'confirmButton' %> To permanently deactivate the link, use the code below ...

Retrieve the specific data from the database when the <tr> element is hovered over

Hey everyone, I've been struggling with a problem for some time now. I have a loop that retrieves values from a database and I want each value to display onmouseover using JavaScript. However, it's only showing the value of the first row for all ...

Exploring the integration of JSONP with the unmatched features of Google

I am attempting to utilize the Google maps directions API by using jquery $.ajax. After checking my developer tools, it seems that the XHR request has been completed. However, I believe there may be an issue with the way jquery Ajax handles JSON.parse. Y ...

Making a secure connection using AJAX and PHP to insert a new row into the database

Explaining this process might be a bit tricky, and I'm not sure if you all will be able to assist me, but I'll give it my best shot. Here's the sequence of steps I want the user to follow: User clicks on an image (either 'cowboys&apos ...

Converting an array of objects to an array based on an interface

I'm currently facing an issue with assigning an array of objects to an interface-based array. Here is the current implementation in my item.ts interface: export interface IItem { id: number, text: string, members: any } In the item.component.ts ...

Troubleshooting Issue: Failure of Ajax Script to Display Saved Data in Edit Function

Whenever I clicked on the Edit icon in the action column of my data tables, the saved data did not display as expected. I noticed that this issue was only occurring for file input types, while it worked properly for text input types. In the Blade file Ad ...

Enhancing appearance with $refs?

Having trouble adding style to the $refs attribute. I keep getting an error message saying "Cannot set property 'cssText' of undefined." Is there a way to accomplish this task? I haven't come across anything similar to this issue before. th ...

:Incorporating active hyperlinks through javascript

Hey there, I've encountered a little conundrum. I have a header.php file that contains all the header information - navigation and logo. It's super convenient because I can include this file on all my pages where needed, making editing a breeze. ...

The code begins executing even before the function has finished its execution

I believe that is what's happening, but I'm not entirely sure. There's code in a .js file that invokes a function from another .js file. This function performs an ajax call to a php page which generates and returns a list of radio buttons wi ...

Attaching an input text box to an Angular $scope is not possible

In my angular app, I have a piece of markup that showcases a table with saved queries. Each query has the option to add a title using an input field. When you click the edit icon, it should display the newly created title. <table class="table table-str ...

I encountered a problem while trying to incorporate the solution that prompts another button click event

Interesting topic: JQuery / JavaScript - triggering button click event from another button <input type="submit" name="savebutton" id="uniqueOne" /> <input type="submit" name="savebutton" id="uniqueTwo" /> I have implemented a feature on my si ...

What methods can be used to broaden configuration variables within VSCode using an extension?

I attempted to develop an extension for vscode that requires reading the pasteImage.parth variable from the ./vscode/settings.json file { "pasteImage.path": "${workspaceRoot}/assets/images" } In my attempt to retrieve the variable us ...

What is the process of extracting data from a variable and inserting it into a JSON object in JavaScript?

I have just started learning about JSON and am currently working on a JavaScript program. I've been searching for a straightforward solution, but I may not be framing my question correctly. My goal is to allow users to input their information which w ...

`Javascript often returns NaN for basic calculations`

Hello, I am currently developing a basic calculator for a game but I have encountered an issue. Despite having just started learning this programming language and reading all available tutorials, I am now in the process of writing code to gain more experie ...