测试具有依赖于另一个模式的验证的猫鼬模式

Testing a mongoose schema that has a validation which depends on another schema

我有一个 mongoose 模式-WishlistItem,它有一个 验证: 如果它是 wishlist [,则无法创建新的 WishlistItem 属性(对象 ID)不属于数据库中真实存在的 WishlistWishlistItem 具有此验证,因此没有父 wishlistswishlistItems 不会意外添加到数据库中。

如何在 WishlistItem 模型上 运行 测试而不创建真实的 wishlist

我正在使用 mocha 和 chai。

创建愿望清单项目的测试

目前测试给出: AssertionError: expected undefined to be an object.

这是因为 await WishlistItem.create({... 抛出错误:

ValidationError: WishlistItem validation failed: wishlist: Invalid WishlistItem "wishlist" property. No wishlist found with id: 5f9480a69c4fcdc78d55397d 因为数据库中没有 wishlist

const chai = require('chai');
const mongoose = require('mongoose');


const { expect } = chai;

const dbConnect = async (dsn) =>
  mongoose.connect(dsn, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
  });

const should = chai.should();
const WishlistItem = require('../testsFiles/WishlistItem.Model');

describe('Wishlist Item', () => {
  before(async () => {
    dbConnect(`mongodb://127.0.0.1:27017/schemaDepTest`);
  });
  context('create wishlist item', () => {
    it('should create a wishlist item with valid arguments', async function () {
      let wishlist;
      try {
        wishlist = await WishlistItem.create({
          itemName: 'Purse',
          price: '5.00',
          wishlist: mongoose.Types.ObjectId('5f9480a69c4fcdc78d55397d'),
        });
      } catch (err) {
        console.log(err);
      }
      expect(wishlist).to.be.an('Object');
    });
  });
});

愿望清单项目架构

const mongoose = require('mongoose');

const itemSchema = new mongoose.Schema(
  {
    itemName: { type: String, required: true, trim: true },
    price: { type: String, required: true, trim: true },
    wishlist: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Wishlist',
      required: true,
    },
  },
  { timestamps: { createdAt: 'created_at' } }
);

itemSchema.path('wishlist').validate(async function (value) {
  const WishlistModel = require('./Wishlist.Model');
  const wishlist = await WishlistModel.findOne({ _id: value });
  if (!wishlist) {
    throw new Error(
      `Invalid WishlistItem "wishlist" property. No wishlist found with id: ${value}`
    );
  } else {
    return true;
  }
}, 'Parent Wishlist non existent');

const WishlistItem = mongoose.model('WishlistItem', itemSchema);
module.exports = WishlistItem;

心愿单架构

const mongoose = require('mongoose');

const wishlistSchema = new mongoose.Schema(
  {
    wishlistName: {
      type: String,
      required: true,
      trim: true,
    },
    wishlistItems: [
      // reference, one-to-many
      {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'WishlistItems',
      },
    ],
    user: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User',
      required: true,
    },
  },
  { timestamps: { createdAt: 'created_at' } }
);

const Wishlist = mongoose.model('Wishlist', wishlistSchema);

module.exports = Wishlist;

我只需要添加 sinon.stub(Object.getPrototypeOf(Wishlist), 'findOne').callsFake(() => 'mock');

这样,当 WishlistItem 试图通过调用 Wishlist.findOne 来验证 Wishlist 是否存在时,() => 'mock' 被调用以代替 findOne

完整测试代码:

const sinon = require('sinon');
const chai = require('chai');
const mongoose = require('mongoose');

const { expect } = chai;

const dbConnect = async (dsn) =>
  mongoose.connect(dsn, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
  });

const should = chai.should();
const WishlistItem = require('../testsFiles/WishlistItem.Model');
const Wishlist = require('../testsFiles/Wishlist.Model');

describe('Wishlist Item: testing dependency mocking ', () => {
  before(async () => {
    dbConnect(`mongodb://127.0.0.1:27017/schemaDepTest`);
  });
  context('create wishlist item', () => {
    it('should create a wishlist item with valid arguments', async function () {
      sinon.stub(Object.getPrototypeOf(Wishlist), 'findOne').callsFake(() => 'mock');

      let wishlist;
      try {
        wishlist = await WishlistItem.create({
          itemName: 'Purse',
          price: '5.00',
          wishlist: mongoose.Types.ObjectId('5f9480a69c4fcdc78d55397d'),
        });
      } catch (err) {
        console.log(err);
      }
      console.log(wishlist);
      expect(wishlist).to.be.an('Object');
    });
  });
});