alonronin/mockingoose

[Question] Check what object has been saved / created

bytefluxio opened this issue ยท 1 comments

Disclaimer: Im somewhat new to javascript, completely new to jest. My question might be stupid - or not - I wouldn't know ๐Ÿ˜…

How would you go about testing what object has been created / saved?

I have a route controller for creating a new object:

const mongoose = require('mongoose');
const status = require('http-status');

const ModelPath = '../../models/'; // Needed for WebStorm...
const User = require(ModelPath + 'user');

module.exports = function(req, res, next) {
  return User
    .find({email: req.body.email})
    .exec()
    .then(checkIfUserIsUnique)
    .then(() => createUser(req))
    .then(user => user.save())
    .then(user => {
      res.status(status.CREATED).json({
        message: 'User created.',
        userId: user._id
      })
    });
};

function checkIfUserIsUnique(users) {
  if (users.length >= 1) {
    const error = new Error('User already exists.');
    error.status = status.CONFLICT;
    throw error;
  }
}

function createUser(req) {
  return new User({
    _id: new mongoose.Types.ObjectId(),
    email: req.body.email,
    password: req.body.password,
    roles: req.body.roles
  });
}

And these are my tests so far:

const mockingoose = require('mockingoose').default;
const express = require('express');
const createUser = require('./create-user');

describe('create user', () => {
  const req = express.request;
  const res = express.response;
  const next = jest.fn();
  const users = [];

  beforeAll(() => {
    mockingoose.User.toReturn(users);
    mockingoose.User.toReturn({ _id: '5b02bc862bb02d8629b7f922' }, 'save');
    req.body.email = 'test@mail.com';
    req.body.password = 'testPassword';
  });

  beforeEach(() => {
    while (users.length > 0) {
      users.pop();
    }
  });

  test('creates a new user', () => {
    let jsonCalledWith;
    res.json.mockImplementation(data => jsonCalledWith = data);

    return createUser(req, res, next)
      .then(() => {
        expect(res.status).toHaveBeenCalledWith(201);
        expect(res.json).toHaveBeenCalled();
        expect(jsonCalledWith.message).toBe('User created.');
        expect(jsonCalledWith.userId.toString()).toBe('5b02bc862bb02d8629b7f922');
      })
  });

  test('creating user if user with that mail already exists fails', () => {
    users.push({ email: 'test@mail.com'});
    let jsonCalledWith;
    res.json.mockImplementation(data => jsonCalledWith = data);

    const result = createUser(req, res, next);
    return result.catch(error => {
      expect(error).toBeDefined();
      expect(error.status).toBe(409);
      expect(error.message).toBe('User already exists.');
    });
  });
});

(express is mocked)

Now I do not only want to check whether the response contains the correct content, but also whether the user has been created correctly (user information taken out of the request and into the constructor).

Is there a way to test this? E.g. checking what arguments the constructor has been called with etc..

this looks ok, however seem not needed, as you don't want to test express but your code logic.
so you can mock the req object, and test only the createUser function, mockingoose helps you to return mocked data without connecting to a db.