Mongoose: OverwriteModelError with mocha "watch"

تم إنشاؤها على ١٤ ديسمبر ٢٠١٢  ·  61تعليقات  ·  مصدر: Automattic/mongoose

لقد قمت للتو بالتحديث من 3.4.0 إلى 3.5.1 ، وعند "مشاهدة" اختبارات Mocha على نموذج ، في كل مرة يتم فيها إعادة تحميل الملف ، أحصل على خطأ OverwriteModel من إعادة طلب - وأعتقد ، إعادة تعريف - النموذج.

يجب أن يكون هناك بعض القيمة في ارتكاب خطأ "الكتابة فوق" ، لكنني سأعود إلى 3.4.0 في الوقت الحالي لأن هذا يمثل الكثير من الألم.

التعليق الأكثر فائدة

هناك خيار آخر: تنظيف النمس من جميع النماذج والمخططات.
في كود الاختبار الخاص بي ، أضفت:

 mongoose.models = {};
 mongoose.modelSchemas = {};

وهو يعمل بشكل جيد ، على الأقل بالنسبة لي.

ال 61 كومينتر

يحدث هذا بسبب خطأ في البرمجة. لا يؤدي استدعاء mongoose.model() أو connection.model() بنفس الاسم والمخطط عدة مرات إلى حدوث خطأ. يؤدي تمرير اسم نموذج موجود بمخطط مختلف إلى حدوث الخطأ. لم يُسمح أبدًا بالكتابة فوق النماذج.

إذا أعادت ساعة mocha طلب مخططك واستدعيت mongoose.model(preExistingName, newSchema) فحينئذٍ ستحصل على خطأ الآن. في السابق في هذا السيناريو ، لم يكن النمس يجمع نموذجًا جديدًا على الإطلاق ، بل كان يبتلع خطأ البرمجة ويعيد النموذج القديم ، وهو سلوك خاطئ.

var schema = new Schema;
var A = mongoose.model('A', schema);
var B = mongoose.model('A', schema); // no error
var C = mongoose.model('A', new Schema); // previously unreported error

حسنًا ، هذا منطقي. شكرا!

aheckmann - أنا --watch وأحصل على

OverwriteModelError: Cannot overwrite "User" model once compiled.

user.js

var mongoose = require('mongoose'),
  Schema = mongoose.Schema,
  ObjectId = mongoose.SchemaTypes.ObjectId;

var userSchema = new Schema({
  name: { type: String }
}), 
  User;

// other virtual / static methods added to schema

User = mongoose.model('User', userSchema);
module.exports = User;

userSpec.js

var User = require('../models/user'),
  mongoose = require('mongoose');

mongoose.connection.on('error', function (err) {
  console.log(err);
}

mongoose.connection.on('open', function () {
  console.log('connected');
}

describe('User', function () {

  before(function (done) {
    mongoose.connect('mongodb://localhost/test');
    done();
  }

  after(function (done) {
    mongoose.disconnect(function () {
      console.log('disconnected');
      done();
    });
  });

  it('should test something', function (done) {
     // tests
     done();
  });
});

بالنسبة لاختبارات النمس ، نقوم فقط بإنشاء اتصالات جديدة في كل مرة وهي تعمل بشكل جيد.

var db = mongoose.createConnection()

https://github.com/LearnBoost/mongoose/blob/master/test/common.js#L74 -L98

متابعة منشورة لمجموعات Google https://groups.google.com/d/topic/mongoose-orm/PXTjqqpaDFk/discussion

أنا أرى هذا أيضًا. إليك مثال بسيط:

https://github.com/j0ni/mongoose-strangeness

ربما أفتقد الطريقة الصحيحة لتحديد النماذج ...؟

https://github.com/j0ni/mongoose-strangeness/blob/master/test.spec.js#L21

يجب أن يكون var Example = connection.model('Example', ExampleSchema)

شكرا @ aheckmann الذي يعمل بشكل رائع.

يعمل ب / كاليفورنيا يتم إنشاء اتصال جديد لكل اختبار من الاختبارات الخاصة بك ويتم تخزين النموذج مؤقتًا محليًا داخل الاتصال لكل منهما. فشل الطريقة الأخرى تم تجميع نماذج ب / ج على مستوى وحدة النمس لكل اختبار ، ومن هنا جاءت التعارضات.

aheckmann - نماذجي في تطبيق Locomotive .

بشكل أساسي ، يقوم كل ملف اختبار بتشغيل تطبيق Locomotive في الوظيفة before() . يؤدي تشغيل التطبيق إلى إنشاء اتصال mongo db وتحميله في جميع نماذجي - وهذا في ملف مُهيئ النمس (يتم تشغيله مرة واحدة عند بدء تشغيل التطبيق):

var mongoose = require("mongoose"),
    fs = require("fs");

module.exports = function() {

  // Connect to DB
  switch (this.env) {
    case 'development':
      mongoose.connect('mongodb://localhost/slipfeed');
      break;
    case 'test':
      mongoose.connect('mongodb://localhost/slipfeed');
      break;
    case 'production':
      mongoose.connect('mongodb://mongodb.example.com/prod');
      break;
  }

  // Load models  
  var app = this,
      modelPath = app.get('models');
  fs.readdirSync(modelPath).forEach(function(file) {
    var name = file.substr(0, file.lastIndexOf('.'));
    require(modelPath + '/' + name)(mongoose, app);
  });

}

في كل ملف من ملفات النموذج الخاصة بي ، أقوم بما يلي في الأساس:

module.exports = function(mongoose, app) {
  var Schema = mongoose.Schema;
  var User = new Schema(...);
  app.User = mongoose.model('User', User);
});

وفي كل ملف من ملفات اختبار النموذج الخاص بي ، أقوم بشيء مثل هذا:

var locomotive = require("locomotive"),
    app = new locomotive.Locomotive(),
    should = require("should");

describe( "User", function() {

  before( function (done) {
    app.boot( process.cwd(), 'test', function () {
      done();
    });
  });

  after( function (done) {
    mongoose.disconnect( function (err) {
      if (err) throw err;
      console.log('DISCONNECT')
      done();
    })
  });      

  ...tests go here

});

يبدأ الجزء app.boot() الخادم ، ويقوم بتحميل ملف التكوين ويتم تشغيله من خلال intializers (وهي عبارة عن ملفات تحتوي على أجزاء مختلفة من التعليمات البرمجية ، على سبيل المثال بدء اتصالات db).

ولكن بعد الانتهاء من ملف الاختبار الأول ، وحاول mocha تحميل الملف التالي ، سأحصل على OverwriteModelError .

أفهم أنه من المحتمل أن يكون له علاقة بعدم إغلاق الاتصالات عند تحميل ملف الاختبار التالي ، أو ربما أقوم بتهيئة النماذج الخاصة بي بطريقة سيئة.

على أي حال ، حاولت إضافة mongoose.disconnect إلى وظائفي after() ، لكن ذلك لم يساعد.

لا علاقة له بالاتصالات المفتوحة أو المغلقة. أنت تحاول إعادة تعريف نموذج موجود بالفعل في مخطط مختلف.

var a = new Schema({ x: 'string' });
var b = new Schema({ x: 'string' });
mongoose.model('Thingy', a);
mongoose.model('Thingy', a); // ok, a === the registered schema instance
mongoose.model('Thingy', b); // error a !== the registered schema

FWIW ، أعتقد أن بعض أمثلة التعليمات البرمجية الأقل تافهة قليلاً ستمنع هذا من الظهور بشكل متكرر. ربما يكون تطبيقًا سريعًا صغيرًا ، والذي يحدد نموذجًا واحدًا ، يهيئ الاتصال بطريقة قابلة للحقن ، واختبار تكامل mocha (في حالتي أنا أستخدم اختبارًا فائقًا ، ولكن أيا كان حقًا) الذي يضخ الاتصال دون إثارة هذه المشكلة.

إذا كان هناك بعض التطبيقات التي تعرفها عن aheckmann والتي يمكننا النظر إليها ، والتي تعتبرها تنفذ نمطًا أساسيًا ، فإن ذلك

إليكم ما لجأت إليه:

https://github.com/j0ni/beachenergy.ca/blob/master/datamodel/index.js

لا يعجبني ، لكنه يجعل المشكلة تختفي. إذا كنت أستخدم نمغًا مضادًا للنمط (يبدو محتملاً) ، فإن المثال الكنسي سيساعد.

مرحبًا aheckmann - أنا متأكد بنسبة 100٪ أنني لا أقوم بإنشاء نموذج جديد بمخطط مختلف. لقد أنشأت مشروعًا هيكليًا / تجريبيًا لتوضيح هذه المشكلة: https://github.com/davisford/mongoose-test

ابدأ موكا make وستنجح الاختبارات في المرة الأولى. الآن ، قم بتحرير models/user.js واحفظ (على سبيل المثال CTRL / CMD + S) ، و mocha تلتقط التغيير بـ --watch ، وضربنا OverwriteModelError .

هنا خيار آخر ... أستخدم nodemon. يضمن ذلك إعادة العملية في كل مرة يتم فيها تشغيل الاختبار:
$ nodemon - اختبار "mocha -R min" exec

إذن ما هو الحل الموصى به لهذا؟ هل تريد إنشاء اتصال جديد قبل كل اختبار؟ وإلا كيف يمكننا تحديد نموذج النمس في مواصفاتنا وعدم وجود خطأ به أثناء المشاهدة؟

لقد تخليت عن محاولة حلها باستخدام الموكا وحدها. بدلاً من ذلك ، ما أفعله هو تشغيل mocha عبر nodemon. بهذه الطريقة ، يتم إعادة تشغيل عملية العقدة ويتم التخلص من المشكلة.

بيتر جراف
(تم إرساله من جهاز iPad ، من المحتمل وجود أخطاء إملائية :)
+1.512.784.3232
بتر. [email protected]

في 2 فبراير 2013 ، في 5:41 صباحًا ، كتب أوليفر جوزيف آش [email protected] :

إذن ما هو الحل الموصى به لهذا؟ هل تريد إنشاء اتصال جديد قبل كل اختبار؟ وإلا كيف يمكننا تحديد نموذج النمس في مواصفاتنا وعدم وجود خطأ به أثناء المشاهدة؟

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub.

كيف تدير المخاوي عبر nodemon بالضبط؟ لقد جربت هذا ، لكنني على الأرجح بعيد:

nodemon /usr/local/share/npm/bin/mocha --reporter spec --ui bdd --watch ./server/test/*.js

أنا أستعمل:
nodemon - اختبار exec "mocha -R min"

بالنظر إلى المثال الذي تعرضه أدناه ، يبدو أنك تستخدم المواصفات بدلاً من min ولديك اختباراتك في الخادم / الاختبار ... إذا كان الأمر كذلك ، فقم فقط بتغيير المعلمات ...

في 2 فبراير 2013 ، في الساعة 7:00 صباحًا ، كتب أوليفر جوزيف آش [email protected] :

كيف تدير المخاوي عبر nodemon بالضبط؟ لقد جربت هذا ، لكنني على الأرجح بعيد:

nodemon / usr / local / share / npm / bin / mocha - مواصفات التقرير --ui bdd --watch ./server/test/*.js
-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub.

هذا لطيف. ليس بنفس سرعة --watch ، لكن الأهم من ذلك أنه يعمل.

لقد لاحظت أيضًا أنه عند إجراء تغييرات على المخطط الذي يتطلبه اختبار Mocha ، لن يقوم Mocha بإعادة تحميلها حيث يتم تخزينها مؤقتًا :(

في 2 فبراير 2013 ، الساعة 15:23 ، كتب Petter Graff [email protected] :

أنا أستعمل:
nodemon - اختبار exec "mocha -R min"

بالنظر إلى المثال الذي تعرضه أدناه ، يبدو أنك تستخدم المواصفات بدلاً من min ولديك اختباراتك في الخادم / الاختبار ... إذا كان الأمر كذلك ، فقم فقط بتغيير المعلمات ...

في 2 فبراير 2013 ، في الساعة 7:00 صباحًا ، كتب أوليفر جوزيف آش [email protected] :

كيف تدير المخاوي عبر nodemon بالضبط؟ لقد جربت هذا ، لكنني على الأرجح بعيد:

nodemon / usr / local / share / npm / bin / mocha - مواصفات التقرير --ui bdd --watch ./server/test/*.js
-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub.

نجح حل

try {
    // Throws an error if "Name" hasn't been registered
    mongoose.model("Name")
} catch (e) {
    mongoose.model("Name", Schema)
}

أوافق على أنه ليس من الجميل أن يضطر المرء إلى إلقاء رمز بمثل هذه المكالمات. سيكون من الجيد أن يكون لديك اختصار لهذا يعمل مع الحالة الأكثر شيوعًا ، وهي أنه يتم ببساطة إعادة تحليل الوحدة في وقت التشغيل دون أي تغيير في المخطط. ربما نسميها شيئًا مثل mongoose.getOrCreate(name, schema) .

yourcelf أخذ اقتراحك وعمل لي. شكرا.

module.exports = getOrCreateModel('User', UserSchema);

هناك خيار آخر: تنظيف النمس من جميع النماذج والمخططات.
في كود الاختبار الخاص بي ، أضفت:

 mongoose.models = {};
 mongoose.modelSchemas = {};

وهو يعمل بشكل جيد ، على الأقل بالنسبة لي.

remicastaing الكمال ، يعمل بالنسبة لي. شكرا!

remicastaing أفضل حل حتى الآن!

remicastaing يعمل أيضًا بالنسبة لي ، ويبدو أنه أفضل حل حتى الآن

remicastaing نعم ، يبدو أنه حل عملي.

ما زالت لا تعرف ما هي المشكلة الفعلية بالرغم من ذلك.

remicastaing شكرًا ، يعمل معي أيضًا!

remicastaing يعمل لي أيضًا. شكرا.

آسف لخدش حكة قديمة ، لكنني أواجه نفس المشكلة في محاولة تشغيل mocha -w مع النمس ، جربت كل الحلول الممكنة ولكني الآن أصطدم بالحائط.

أين يجب أن أضع

 mongoose.models = {};
 mongoose.modelSchemas = {};

؟

قبل كل ، بعد كل بعد ، قبل ، قبل؟

هل يجب عليّ mongoose.createConnection () تشغيله قبل كل ، وإغلاقه بعد كل؟

أضع

mongoose.models = {};
mongoose.modelSchemas = {};

مباشرة بعد

var mongoose = require('mongoose');

في ملف config.test.js مباشرة في المجلد test ( config.test.js الملف الوحيد *.test.js في مجلد الاختبار ، ملفات أخرى *.test.js موجودة المجلدات الفرعية). مع انتقال الموكا بشكل متكرر (الخيار --recursive في mocha.opts ) من خلال مجلد الاختبار ، يبدأ بـ config.test.js .

Remicastaing شكرا! اعمل معي ايضا (ياسمين)

مجرد حالة أخرى:
واجهت هذه المشكلة ، عندما طلبت نموذجًا بأحرف مختلفة في الرمز وفي الاختبار.
على سبيل المثال في المواصفات:
var User = require('./models/user');
وفي الكود
var User = require('./models/User');
فقط ضع في اعتبارك ، لم يكن هناك نسخة مخبأة للكتابة المختلفة

+1 ما شهدهasci . إذا كنت تحتاج إلى نفس النموذج ولكن مع حالة مختلفة في ملفين مختلفين ، ثم طلبت ذلك في ملف آخر ، فسيؤدي ذلك إلى ظهور الخطأ "لا يمكن الكتابة فوق"

iandoe أستخدم mongoose.connect وأدخل اختبار المخاوي

after(function(done){
  mongoose.models = {};
  mongoose.modelSchemas = {};
  mongoose.connection.close();
  done();
});

: +1:: القوس:

: +1:

إذا كنت تريد إنشاء نموذج في beforeEach ، فأنشئ اتصالًا جديدًا بـ var db = mongoose.createConnection(); ثم db.model(...) بدلاً من mongoose.model(...); في beforeEach . هذا السلوك حسب التصميم وليس خطأ.

لدي رمز يمكن إعادة تحميله في وقت التشغيل ، لذا أريد استبدال نموذج موجود إذا قمت بإجراء تغيير على المخطط أو وظائف النموذج أثناء التطوير.

ما لم يكن هناك سبب وجيه لعدم عدم فهمي لماذا لا يجب أن أكون قادرًا على فعل شيء كهذا.

مثال

delete mongoose.models['somemodel'];
var somemodel = db.mongoose.model('somemodel', someschema);

هذا يعمل بالنسبة لي ، لقد كنت أفعل ذلك بهذه الطريقة لمدة عام تقريبًا.

أو ربما تكون هناك طريقة لتغيير وظائف المخطط والنموذج دون مسح نموذج / مخطط موجود ولكني لم أزعج نفسي لمزيد من البحث.

يمكن أن يكون هذا الحل مفيدًا

yourcelf لديه الحق.

: +1:

أعلم أن هذا قديم ولكن إذا تعثر أي شخص في ذلك ، فقد قمت بحله عن طريق إنشاء ملف أداة مساعدة لاختبار قاعدة البيانات مثل هذا:

// DatabaseUtils.js
import mongoose from 'mongoose';
const MONGO_URI = 'mongodb://localhost:27017/collectionname'

export function tearDown(){
  mongoose.models = {};
  mongoose.modelSchemas = {};
  resetDb();
  if(mongoose.connection.readyState) mongoose.disconnect();
}

export function setUp(){
  if(!mongoose.connection.readyState) mongoose.connect(MONGO_URI);
}

export function resetDb(){
  if(mongoose.connection.db) mongoose.connection.db.dropDatabase();
}

ثم من ملف الاختبار الخاص بك يمكنك استخدام:

import { setUp, tearDown, resetDb } from './DatabaseUtils'

describe('Testing MongoDB models', function(){
  before(setUp)
  after(tearDown)
  afterEach(resetDb)

  it('Some test of a mongoose model', () =>  {
  // Test code here.
  }
})

هذه الإجابة StackOverflow تحلها كما يلي:

let users
try { users = mongoose.model('users') }
catch (e) { users = mongoose.model('users', <UsersSchema...>) }

تحرير: كما أشار DanielRamosAcosta ، "المشكلة هي أنه إذا تغير فلن تؤثر التغييرات."

شكرًا remicastaing ، لقد خسرت 5 دقائق حتى وصلت إلى الحل الخاص بك ، يجب أن يكون أكثر وضوحًا :)

شكرًا juanpabloaj ، لقد

gunar المشكلة هي أنه إذا تغير

تضمين التغريدة

أنا ببساطة استخدم ، بدلاً من إنشاء تجربة / قبض قبيح:

let users = mongoose.models.users || mongoose.model('users', <UsersSchema...>)

هذه المناقشة مخزية حقا
أعطى المؤلفون الفعليون للنمس الحل الصحيح ( 1 و 2 ) ومع ذلك فإن جميع عمليات الإبهام تذهب إلى حلول اختراق غير صحيحة.
حقا مخجل

@ tomyam1 ، ربما لأن تلك الحلول المبتكرة تحل مشاكلنا دون أي مشاكل ...: مبتسم:

في بعض الأحيان ، يعمل الحل المناسب بشكل أفضل من الحل الصحيح تقنيًا :)

@ tomyam1 لا يوجد شيء مخجل في التعاون لحل مشكلة وأنا ممتن لكل من نشر رأيهم الخاص حول الحل هنا. بدون الخوض في التفاصيل - في حالتي ، نجح أحد اقتراحات "الاختراق غير الصحيحة" على أكمل وجه ، وكلا ما تسميه بالحلول "الصحيحة" لم يعمل.

مساعدة بعضنا البعض ليست مخزية. شكرا لكل من قدم مشاركة بناءة

حسنًا يا سادة (garethdown44 ، fega) ، ثم نختلف.
لتجنب إنشاء المزيد من البريد العشوائي ، يرجى استخدام ردود فعل الرموز التعبيرية.

لتلخيص هذا الموضوع:

لا يوجد سوى ثلاثة حلول مختلفة في هذه الصفحة:

  1. استخدم النموذج المخزن مؤقتًا إذا كان موجودًا:
mongoose.models.users || mongoose.model('users', <UsersSchema...>)

أو

try {
    // Throws an error if "Name" hasn't been registered
    mongoose.model("Name")
} catch (e) {
    mongoose.model("Name", Schema)
}

هذا ليس حلاً لأنه لن يلتقط التغييرات في النماذج.

  1. امسح ذاكرة التخزين المؤقت للنموذج
 mongoose.models = {};
 mongoose.modelSchemas = {};

جربت هذا الحل ولم ينجح ومن يدري لماذا؟
يعتمد على تعديل المتغيرات الداخلية غير الموثقة.
من المحتمل أنها نجحت عندما تم اقتراحها في عام 2013 ، لكنها بعد 4 سنوات.

  1. احفظ النموذج على الاتصال.
    هذا هو الحل الرسمي الذي اقترحه مؤلفو mogoose.
    ومع ذلك تم تجاهله بالكامل تقريبًا. بالنسبة لي ، هذا أمر مخز.
const Mongoose = require('mongoose');
const DB = Mongoose.createConnection(...);
const Model = DB.model("Name", schema);

@ tomyam1 - توافق من حيث المبدأ على ما تقوله. ولكن لكي نكون منصفين أن الحل جاء بعد عامين من الحل (الاختراق) الآخر !!

في حالتي اخترت حل nodemon. عندما أدركت ما كان يحدث والطريقة التي تم بها هيكلة كود الاختبار ، كان سيتطلب إعادة هيكلة كبيرة ليس لدي وقت للقيام بها. أنا سعيد لأنه تم اقتراح حل nodemon وأن الأشخاص أجروا 1+ له. هذا كل ما أقوله.

للأسف ، يقوم Nodemon بإعادة تشغيل مجموعة الاختبار بأكملها. إعادة تحميل mocha --watch أسرع بكثير

للأسف ، يقوم Nodemon بإعادة تشغيل مجموعة الاختبار بالكامل ، لذا فإن إعادة تحميل mocha --watch أسرع بكثير

إعادة تحميل بطيئة ومطور عاقل هو المقايضة التي سأجعلها أكثر من تقطيع ميلي ثانية (أو ثوان) من تشغيل اختباري.

أيضًا ، نظرًا لأنه لم يتم ذكره هنا ، فإن npm-watch هو أداة للقيام بذلك (وهو يلتف nodemon) بحيث يمكنك تحديد نص بسيط npm watch https: //www.npmjs. كوم / حزمة / npm- مشاهدة

كانت لدي نفس المشكلة ، لذا قمت بفحص mongoose.modelNames() وحدد ما إذا كنت أقوم بتجميع النموذج أو استردت النموذج المترجم بالفعل ، لأن mocha --watch تسبب هذه المشكلة. إذن هذا هو الكود:

mongoose.modelNames().indexOf("User") === -1 //if my model has not been compiled...
 ? mongoose.model("User", UserSchema) //...compile model and return it
 : mongoose.connection.model("User"); //else it is already compiled, so return this model

الآن تعيد هذا كدالة (استبدل "المستخدم" بالمتغير ، و UserSchema بالمتغير الخاص بالمخطط الخاص بك) مقابل module.exports وعندما تطلب ذلك يمكنك استدعاء هذه الوظيفة.

https://stackoverflow.com/a/49806603/5674976

remicastaing يعمل مثل السحر ، شكرا!

في بعض عمليات إنشاء مثيل خاصة ، قد يلزم مسح مراجع models

after((done) => {
  Object.keys(mongoose.models).forEach((k) => {
    delete mongoose.models[k];
  });
  Object.keys(mongoose.modelSchemas).forEach((k) => {
    delete mongoose.modelSchemas[k];
  });
  mongoose.connection.close();
  done();
});

لا تتطلب mocha --watch أي شيء خارج describe ، أي لن تعيد تعريف المخططات الخاصة بك.

الطريقة الأكثر فاعلية وأناقة ومفهومة للاختبار التي تحقق أقل عدد من الاتصالات بـ db هي إعداد الاتصال والمخططات والنماذج الخاصة بك خارج مجموعة الاختبار الخاصة بك.

هذا الرمز جاف جدًا مقارنة بمثالي الآخر لإعداد نموذج قبل كل اختبار (ليس ضروريًا بالنسبة لي).

تعمل مجموعة الاختبارات التالية:

const expect = require("chai").expect;
const mongoose = require("mongoose"),
  UserSchema = require("../data/models/User");
const connection = mongoose.createConnection(
  process.env.MONGO_URL || "mongodb://127.0.0.1/test"
);
const User = connection.model("User", UserSchema);

describe("Database Testing", function() {
  it("MongoDB is working and repeatedly testable", function(done) {
    let user = User({
      username: "My user"
    });

    user
      .save()
      .then(doc => {
        console.log(doc); // This outputs the doc.
        expect(doc.username).to.equal("My user");
        done();
      })
      .catch(err => {
        console.error(err);
        expect(err).to.be.null;
        done();
      });
  });
});

من ../data/models/User.js

let mongoose = require("mongoose");

let UserSchema = new mongoose.Schema({
  username: String
});
module.exports = UserSchema; // 

اعتدت أن أكون في حالة ارتباك حول كيفية قيام MongoDb بإجراء اتصالاتها ومخططاتها ونماذجها. لم أكن أدرك أنه يمكنك تحديد نموذج واحد واستخدامه عدة مرات (obv. لكن ...)

لقد اتبعت الوثائق تمامًا وصنعت وحدة تعرّف المخطط وأعدت نموذجًا.

هذا يعني أنه إذا طلبت ذلك في اختبار ، فسيتم إعادة تعريف المخطط عدة مرات ، لأنه يستمر في طلب الوحدة النمطية التي تحدد المخطط. والتعريفات المتعددة للمخطط ليست بوينو.

تتيح لك حلول الأشخاص (التي تعمل ، وإن كانت أقل كفاءة) إنشاء اتصال جديد قبل كل اختبار ، وغالبًا ما يتم استخدام نموذج جديد قبل كل اختبار.

لكن فهم بسيط أن:

  • لا تنفذ mocha --watch أي شيء خارج describe أكثر من مرة
  • يمكنك استخدام نفس الاتصال والمخطط والنموذج عدة مرات لأشياء مختلفة.

حل هذا بكفاءة وأناقة.

فيما يلي طريقتي الأصلية الأقل كفاءة لجعل هذا يعمل.

./test/db.spec.js

const expect = require("chai").expect;
const mongoose = require("mongoose"),

  // mocha --watch does not rerequire anything
  // outside of the test suite ("describe").
  // Define your Schemas and models separately, so
  // that you can define your Schema once above
  // your test suites, and your models many times
  // when testing. 
  UserSchema = require("../data/models/User");

describe("mongoose strangeness", function() {
  var connection = mongoose.createConnection(
    process.env.MONGO_URL || "mongodb://127.0.0.1/test"
  );

  // I tried the beforeEach and afterEach, but this wasn't needed:

  // beforeEach(function(done) {
  //   connection = mongoose.createConnection(
  //     process.env.MONGO_URL || "mongodb://127.0.0.1/test"
  //   );
  //   connection.once("open", function() {
  //     done();
  //   });
  // });

  // afterEach(function(done) {
  //   connection.close(function() {
  //     done();
  //   });
  // });

  it("MongoDB testable", function(done) {
    let User = connection.model("User", UserSchema);

    let user = User({
      username: "My user"
    });

    user
      .save()
      .then(doc => {
        console.log(doc); // This outputs the doc every time.
        expect(doc.username).to.equal("My user");
        done();
      })
      .catch(err => {
        console.error(err);
        expect(err).to.be.null;
        done();
      });
  });
});

سعيد MongoDbing.

يعمل هذا الرمز بالنسبة لي:

if (mongoose.modelNames().includes('Model')) {
    mongoose.deleteModel('Model');
}

mongoose.model('Model', new mongoose.Schema({ ... }));

verheyenkoen على حق. إليك الرابط إلى مستندات deleteModel: https://mongoosejs.com/docs/api/connection.html#connection_Connection -deleteModel

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات