Mongoose: ๋ชจ์นด 'watch'๋กœ ModelError ๋ฎ์–ด์“ฐ๊ธฐ

์— ๋งŒ๋“  2012๋…„ 12์›” 14์ผ  ยท  61์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Automattic/mongoose

๋ฐฉ๊ธˆ 3.4.0์—์„œ 3.5.1๋กœ ์—…๋ฐ์ดํŠธํ–ˆ์œผ๋ฉฐ ๋ชจ๋ธ์—์„œ Mocha ํ…Œ์ŠคํŠธ๋ฅผ '๊ด€์ฐฐ'ํ•  ๋•Œ ํŒŒ์ผ์ด ๋‹ค์‹œ ๋กœ๋“œ๋  ๋•Œ๋งˆ๋‹ค ๋ชจ๋ธ์„ ๋‹ค์‹œ '์š”๊ตฌ'ํ•˜๋ฉด์„œ OverwriteModelError๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

'๋ฎ์–ด์“ฐ๊ธฐ' ์˜ค๋ฅ˜๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์•ฝ๊ฐ„์˜ ๊ฐ€์น˜๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๊ฒƒ์ด ๋„ˆ๋ฌด ๊ณ ํ†ต์Šค๋Ÿฝ๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ์€ 3.4.0์œผ๋กœ ๋Œ์•„๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ชจ๋ธ๊ณผ ์Šคํ‚ค๋งˆ์—์„œ ๋ชฝ๊ตฌ์Šค๋ฅผ ์ฒญ์†Œํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋‚ด ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ์ ์–ด๋„ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  61 ๋Œ“๊ธ€

์ด๊ฒƒ์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜๋กœ ์ธํ•ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์ด๋ฆ„๊ณผ ์Šคํ‚ค๋งˆ๋กœ mongoose.model() ๋˜๋Š” connection.model() ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•ด๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์Šคํ‚ค๋งˆ๋กœ ์กด์žฌํ•˜๋Š” ๋ชจ๋ธ์˜ ์ด๋ฆ„์„ ์ „๋‹ฌํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ ๋ฎ์–ด์“ฐ๊ธฐ๋Š” ์‹ค์ œ๋กœ ํ—ˆ์šฉ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

mocha watch๊ฐ€ ์Šคํ‚ค๋งˆ๋ฅผ ๋‹ค์‹œ ์š”๊ตฌํ•˜๊ณ  mongoose.model(preExistingName, newSchema) ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ด์ œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด์ „์— ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ mongoose๋Š” ์ƒˆ ๋ชจ๋ธ์„ ์ „ํ˜€ ์ปดํŒŒ์ผํ•˜์ง€ ์•Š๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์˜ค๋ฅ˜๋ฅผ ์‚ผํ‚ค๊ณ  ์ด์ „ ๋ชจ๋ธ์„ ๋ฐ˜ํ™˜ํ–ˆ๋Š”๋ฐ ์ด๋Š” ์ž˜๋ชป๋œ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

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 -- ๋‚˜๋„ ์ด๊ฒƒ์„ ์น˜๊ณ  ์žˆ๋Š”๋ฐ ๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค. ์•„๋ž˜๋Š” ์ œ๊ฐ€ ์„ค์ •ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๊นจ๋—ํ•œ ํ…Œ์ŠคํŠธ ์‹คํ–‰์€ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์„ ํŽธ์ง‘ํ•˜๊ณ  ์ €์žฅํ•˜๋ฉด mocha๊ฐ€ --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) ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š”

๊ฐ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ์ƒˆ ์—ฐ๊ฒฐ์ด ์ƒ์„ฑ๋˜๊ณ  ๋ชจ๋ธ์ด ๊ฐ๊ฐ์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ ๋‚ด์—์„œ ๋กœ์ปฌ๋กœ ์บ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์‹คํŒจํ•˜๋ฉด b/c ๋ชจ๋ธ์ด ๊ฐ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ๋ชฝ๊ตฌ์Šค ๋ชจ๋“ˆ ์ˆ˜์ค€์—์„œ ์ปดํŒŒ์ผ๋˜๋ฏ€๋กœ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

@aheckmann - ๊ธฐ๊ด€์ฐจ ์•ฑ์—์„œ ๋‚ด ๋ชจ๋ธ์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์€ before() ํ•จ์ˆ˜์—์„œ Locomotive ์•ฑ์„ ๋ถ€ํŒ…ํ•ฉ๋‹ˆ๋‹ค. ์•ฑ์„ ๋ถ€ํŒ…ํ•˜๋ฉด mongo db ์—ฐ๊ฒฐ์ด ์ƒ์„ฑ๋˜๊ณ  ๋ชจ๋“  ๋ชจ๋ธ์—์„œ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด mongoose ์ด๋‹ˆ์…œ๋ผ์ด์ € ํŒŒ์ผ์— ์žˆ์Šต๋‹ˆ๋‹ค(์•ฑ ์‹œ์ž‘ ์‹œ ํ•œ ๋ฒˆ ์‹คํ–‰).

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() ๋ถ€๋ถ„์€ ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ๊ตฌ์„ฑ ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๊ณ  ์ดˆ๊ธฐํ™” ํ”„๋กœ๊ทธ๋žจ(์˜ˆ: db ์—ฐ๊ฒฐ ์‹œ์ž‘๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ์ฝ”๋“œ ์กฐ๊ฐ์„ ํฌํ•จํ•˜๋Š” ํŒŒ์ผ)์„ ํ†ตํ•ด ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ฒซ ๋ฒˆ์งธ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์ด ์™„๋ฃŒ๋œ ํ›„ mocha๊ฐ€ ๋‹ค์Œ ํŒŒ์ผ์„ ๋กœ๋“œํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋ฉด OverwriteModelError ๋ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์„ ๋กœ๋“œํ•  ๋•Œ ์—ฐ๊ฒฐ์ด ๋‹ซํžˆ์ง€ ์•Š๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ๋ฐฉ์‹์œผ๋กœ ๋ชจ๋ธ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Œ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

์–ด์จŒ๋“  after() ํ•จ์ˆ˜์— mongoose.disconnect ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์ง€๋งŒ ๋„์›€์ด ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐฉ ๋˜๋Š” ํ์‡„ ์—ฐ๊ฒฐ๊ณผ๋Š” ์•„๋ฌด ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์Šคํ‚ค๋งˆ์— ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋ชจ๋ธ์„ ์žฌ์ •์˜ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

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, ์•ฝ๊ฐ„ ๋œ ์‚ฌ์†Œํ•œ ์˜ˆ์ œ ์ฝ”๋“œ๊ฐ€ ์ด๊ฒƒ์ด ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋‹จ์ผ ๋ชจ๋ธ์„ ์ •์˜ํ•˜๋Š” ์ž‘์€ ์ต์Šคํ”„๋ ˆ์Šค ์•ฑ์€ ์ฃผ์ž… ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์œผ๋กœ ์—ฐ๊ฒฐ์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์ด ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š๊ณ  ์—ฐ๊ฒฐ์„ ์ฃผ์ž…ํ•˜๋Š” ๋ชจ์นด ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ(์ œ ๊ฒฝ์šฐ์—๋Š” supertest๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋ฌด์—‡์ด๋“  ๊ฐ„์—)๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

@aheckmann์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๊ณ  ํ‘œ์ค€ ํŒจํ„ด์„ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š” ์•ฑ์ด ์žˆ๋‹ค๋ฉด ํŠธ๋ฆญ์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์˜์ง€ ํ•œ ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ข‹์•„ํ•˜์ง€ ์•Š์ง€๋งŒ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๋ชฝ๊ตฌ์Šค ์•ˆํ‹ฐ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ(์•„๋งˆ๋„) ์ •์‹ ์˜ˆ์ œ๊ฐ€ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @aheckmann -- ์ €๋Š” ๋‹ค๋ฅธ ์Šคํ‚ค๋งˆ๋กœ ์ƒˆ ๋ชจ๋ธ์„ ๋งŒ๋“ค์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  100% ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์Šค์ผˆ๋ ˆํ†ค/๋ฐ๋ชจ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. https://github.com/davisford/mongoose-test

make mocha๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ฒ˜์Œ์œผ๋กœ ํ†ต๊ณผํ•˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ models/user.js ํŽธ์ง‘ํ•˜๊ณ  ์ €์žฅ(์˜ˆ: CTRL/CMD + S)ํ•˜๋ฉด mocha๊ฐ€ --watch ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์„ ํƒํ•˜๊ณ  OverwriteModelError .

์—ฌ๊ธฐ ๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค... ์ €๋Š” nodemon์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.
$ nodemon --exec "mocha -R min" ํ…Œ์ŠคํŠธ

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์†”๋ฃจ์…˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๊ฐ ํ…Œ์ŠคํŠธ ์ „์— ์ƒˆ ์—ฐ๊ฒฐ์„ ๋งŒ๋“œ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์–‘์—์„œ Mongoose ๋ชจ๋ธ์„ ์ •์˜ํ•˜๊ณ  ์‹œ์ฒญํ•˜๋Š” ๋™์•ˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋ชจ์นด๋งŒ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค๋‹ค๊ฐ€ ํฌ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ๋‚ด๊ฐ€ํ•˜๋Š” ์ผ์€ nodemon์„ ํ†ตํ•ด mocha๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋…ธ๋“œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘๋˜๊ณ  ๋ฌธ์ œ๊ฐ€ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

ํ”ผํ„ฐ ๊ทธ๋ผํ”„
(๋‚ด ์•„์ดํŒจ๋“œ์—์„œ ๋ณด๋‚ด์„œ ์ฒ ์ž ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Œ)
+1.512.784.3232
ํ”ผํ„ฐ. [email protected]

2013๋…„ 2์›” 2์ผ ์˜ค์ „ 5์‹œ 41๋ถ„์— Oliver Joseph Ash [email protected]์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด์— ๋Œ€ํ•œ ๊ถŒ์žฅ ์†”๋ฃจ์…˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๊ฐ ํ…Œ์ŠคํŠธ ์ „์— ์ƒˆ ์—ฐ๊ฒฐ์„ ๋งŒ๋“œ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์–‘์—์„œ Mongoose ๋ชจ๋ธ์„ ์ •์˜ํ•˜๊ณ  ์‹œ์ฒญํ•˜๋Š” ๋™์•ˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.

nodemon์„ ํ†ตํ•ด mocha๋ฅผ ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ด๊ฒƒ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์•„๋งˆ๋„ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

๋‚˜๋Š” ์‚ฌ์šฉํ•œ๋‹ค:
nodemon --exec "mocha -R min" ํ…Œ์ŠคํŠธ

์•„๋ž˜์— ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ๋ฅผ ๋ณด๋ฉด min์ด ์•„๋‹Œ spec์„ ์‚ฌ์šฉํ•˜๊ณ  ์„œ๋ฒ„/ํ…Œ์ŠคํŠธ์— ํ…Œ์ŠคํŠธ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค... ๊ทธ๋ ‡๋‹ค๋ฉด ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค...

2013๋…„ 2์›” 2์ผ ์˜ค์ „ 7์‹œ์— Oliver Joseph Ash [email protected]์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

nodemon์„ ํ†ตํ•ด mocha๋ฅผ ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ด๊ฒƒ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์•„๋งˆ๋„ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

nodemon /usr/local/share/npm/bin/mocha --reporter ์‚ฌ์–‘ --ui bdd --watch ./server/test/*.js
โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.

์ข‹์€๋ฐ. --watch ๋งŒํผ ๋น ๋ฅด์ง€๋Š” ์•Š์ง€๋งŒ ๋” ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ Mocha ํ…Œ์ŠคํŠธ์— ํ•„์š”ํ•œ ์Šคํ‚ค๋งˆ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด Mocha๊ฐ€ ์บ์‹œ๋  ๋•Œ ๋‹ค์‹œ ๋กœ๋“œํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

2013๋…„ 2์›” 2์ผ 15:23์— Peter Graff [email protected]์ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์‚ฌ์šฉํ•œ๋‹ค:
nodemon --exec "mocha -R min" ํ…Œ์ŠคํŠธ

์•„๋ž˜์— ๋ณด์—ฌ์ฃผ๋Š” ์˜ˆ๋ฅผ ๋ณด๋ฉด min์ด ์•„๋‹Œ spec์„ ์‚ฌ์šฉํ•˜๊ณ  ์„œ๋ฒ„/ํ…Œ์ŠคํŠธ์— ํ…Œ์ŠคํŠธ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค... ๊ทธ๋ ‡๋‹ค๋ฉด ๋งค๊ฐœ๋ณ€์ˆ˜๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค...

2013๋…„ 2์›” 2์ผ ์˜ค์ „ 7์‹œ์— Oliver Joseph Ash [email protected]์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

nodemon์„ ํ†ตํ•ด mocha๋ฅผ ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ด๊ฒƒ์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์•„๋งˆ๋„ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

nodemon /usr/local/share/npm/bin/mocha --reporter ์‚ฌ์–‘ --ui bdd --watch ./server/test/*.js
โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.

@j0ni ์˜ ์†”๋ฃจ์…˜์€ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. "mongoose.model"์— ๋Œ€ํ•œ ๋ชจ๋“  ํ˜ธ์ถœ์„ ๋‹ค์Œ์œผ๋กœ ๋Œ€์ฒดํ–ˆ์Šต๋‹ˆ๋‹ค.

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 ์™„๋ฒฝ, ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”!

@remicasting ์ง€๊ธˆ๊นŒ์ง€ ์ตœ๊ณ ์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•!

@remicastaing ๋˜ํ•œ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ์œผ๋ฉฐ ์ง€๊ธˆ๊นŒ์ง€ ์ตœ๊ณ ์˜ ์†”๋ฃจ์…˜ ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค

@remicastaing ์˜ˆ, ์ž‘๋™ํ•˜๋Š” ์†”๋ฃจ์…˜์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ ๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•„์ง ๋ชจ๋ฆ…๋‹ˆ๋‹ค.

@remicastaing ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, ์ €์—๊ฒŒ๋„ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค!

@remicastaing ์ €์—๊ฒŒ๋„ ์ผํ•˜๊ณ  โ€‹โ€‹์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”.

์˜ค๋ž˜๋œ ๊ฐ€๋ ค์›€์ฆ์„ ๊ธ์–ด ๋ฏธ์•ˆํ•˜์ง€๋งŒ ๋ชฝ๊ตฌ์Šค์™€ ํ•จ๊ป˜ mocha -w๋ฅผ ์‹คํ–‰ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์†”๋ฃจ์…˜์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ง€๊ธˆ์€ ๋ฒฝ์— ๋ถ€๋”ชํžˆ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋””์— ๋„ฃ์–ด์•ผ ํ•˜๋‚˜

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

?

์ „๊ฐ, ํ›„๊ฐ, ํ›„, ์ „?

beforeEach์—์„œ mongoose.createConnection(), afterEach์—์„œ ๋‹ซ์•„์•ผ ํ•˜๋‚˜์š”?

๋‚˜๋Š” ๋„ฃ์–ด

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 ํ•ฉ๋‹ˆ๋‹ค.

@remicasting ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚  ์œ„ํ•ด ์ผํ•ด (jasmine)

๋˜ ๋‹ค๋ฅธ ๊ฒฝ์šฐ:
์ฝ”๋“œ์™€ ํ…Œ์ŠคํŠธ์—์„œ ๋Œ€์†Œ๋ฌธ์ž๊ฐ€ ๋‹ค๋ฅธ ๋ชจ๋ธ์ด ํ•„์š”ํ•  ๋•Œ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์–‘์—์„œ:
var User = require('./models/user');
๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ์—์„œ
var User = require('./models/User');
๋‹ค๋ฅธ ํƒ€์ดํ•‘์— ๋Œ€ํ•œ ์บ์‹œ๋œ ๋ฒ„์ „์ด ์—†๋‹ค๋Š” ๊ฒƒ์„ ๋ช…์‹ฌํ•˜์‹ญ์‹œ์˜ค.

@asci๊ฐ€ ๊ฒฝํ—˜ํ•œ ๊ฒƒ์— +1. ๋™์ผํ•œ ๋ชจ๋ธ์ด ํ•„์š”ํ•˜์ง€๋งŒ ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ ํŒŒ์ผ์— ๋‹ค๋ฅธ ๋Œ€์†Œ๋ฌธ์ž๊ฐ€ ์žˆ๊ณ  ๋‹ค๋ฅธ ํŒŒ์ผ์— ํ•„์š”ํ•œ ๊ฒฝ์šฐ '๋ฎ์–ด์“ธ ์ˆ˜ ์—†์Œ' ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

@iandoe ๋‚˜๋Š” mongoose.connect ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ชจ์นด ํ…Œ์ŠคํŠธ๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.

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

:+1: :ํ™œ:

:+1:

beforeEach ์—์„œ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด mongoose.model(...); ์—์„œ beforeEach mongoose.model(...); ์™€ ๋‹ฌ๋ฆฌ var db = mongoose.createConnection(); ๋กœ ์ƒˆ ์—ฐ๊ฒฐ์„ ๋งŒ๋“  ๋‹ค์Œ db.model(...) ๋กœ ์—ฐ๊ฒฐํ•˜์‹ญ์‹œ์˜ค. . ์ด ๋™์ž‘์€ ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๋ผ ์˜๋„์ ์œผ๋กœ ์„ค๊ณ„๋œ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

๋Ÿฐํƒ€์ž„์— ๋‹ค์‹œ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ๊ฐœ๋ฐœ ์ค‘์— ์Šคํ‚ค๋งˆ ๋˜๋Š” ๋ชจ๋ธ ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•˜๋ฉด ๊ธฐ์กด ๋ชจ๋ธ์„ ๋ฎ์–ด์“ฐ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์•ˆ ํ•  ์ด์œ ๊ฐ€ ์—†๋Š” ํ•œ ์ด๋Ÿฐ ์ผ์„ ํ•˜๋ฉด ์•ˆ ๋˜๋Š” ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ

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

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š” ์•ฝ 1๋…„ ๋™์•ˆ ๊ทธ๋ ‡๊ฒŒ ํ•ด์™”์Šต๋‹ˆ๋‹ค.

๋˜๋Š” ๊ธฐ์กด ๋ชจ๋ธ/์Šคํ‚ค๋งˆ๋ฅผ ์ง€์šฐ์ง€ ์•Š๊ณ  ์Šคํ‚ค๋งˆ ๋ฐ ๋ชจ๋ธ ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๋” ์ด์ƒ ์กฐ์‚ฌํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

:+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 ๊ฐ์‚ฌ

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค @juanpabloaj , ์ €์—๊ฒŒ ๋„์›€์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค ๐ŸŽ‰

@gunar ๋ฌธ์ œ๋Š” ์Šคํ‚ค๋งˆ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@juanpabloaj ๊ณ ๋งˆ์›Œ ํ˜•!

์ถ”ํ•œ try/catch๋ฅผ ๋งŒ๋“œ๋Š” ๋Œ€์‹  ๋‹ค์Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

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

์ด ํ† ๋ก ์€ ์ •๋ง ๋ถ€๋„๋Ÿฝ๋‹ค.
mongoose์˜ ์‹ค์ œ ์ž‘์„ฑ์ž๋Š” ์˜ฌ๋ฐ”๋ฅธ ์†”๋ฃจ์…˜( 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 - ๋ง์”€ํ•˜์‹  ๋‚ด์šฉ์— ์›์น™์ ์œผ๋กœ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ณต์ •ํ•˜๊ฒŒ ๊ทธ ์†”๋ฃจ์…˜์€ ๋‹ค๋ฅธ (ํ•ดํ‚ค) ์†”๋ฃจ์…˜๋ณด๋‹ค 2๋…„ ํ›„์— ๋‚˜์™”์Šต๋‹ˆ๋‹ค!!

์ œ ๊ฒฝ์šฐ์—๋Š” nodemon ์†”๋ฃจ์…˜์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š”์ง€ ๊นจ๋‹ฌ์•˜์„ ๋•Œ ํ•  ์‹œ๊ฐ„์ด ์—†๋Š” ํฐ ๋ฆฌํŒฉํ† ๋ง์ด ํ•„์š”ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. nodemon ์†”๋ฃจ์…˜์ด ์ œ์•ˆ๋˜๊ณ  ์‚ฌ๋žŒ๋“ค์ด +1ํ•˜๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒŒ ๋‹ค์•ผ

์Šฌํ”„๊ฒŒ๋„ Nodemon์€ ์ „์ฒด ํ…Œ์ŠคํŠธ ์ œํ’ˆ๊ตฐ์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. mocha --watch ์žฌ์žฅ์ „ ์†๋„๊ฐ€ ํ›จ์”ฌ ๋นจ๋ผ์กŒ์Šต๋‹ˆ๋‹ค.

์Šฌํ”„๊ฒŒ๋„ Nodemon์€ ์ „์ฒด ํ…Œ์ŠคํŠธ ์ œํ’ˆ๊ตฐ์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ฏ€๋กœ mocha --watch๊ฐ€ ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ๋‹ค์‹œ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.

๋Š๋ฆฐ ์žฌ๋กœ๋“œ ๋ฐ ์ •์ƒ์ ์ธ ๊ฐœ๋ฐœ์ž๋Š” ํ…Œ์ŠคํŠธ ์‹คํ–‰์—์„œ ๋ฐ€๋ฆฌ์ดˆ(๋˜๋Š” ๋ช‡ ์ดˆ)๋ฅผ ์Šฌ๋ผ์ด์‹ฑํ•˜๋Š” ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ ์—ฌ๊ธฐ์— ์–ธ๊ธ‰๋˜์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ npm-watch ๋Š” ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋„๊ตฌ(nodemon์„ ๋ž˜ํ•‘)์ด๋ฏ€๋กœ ๊ฐ„๋‹จํ•œ npm ์Šคํฌ๋ฆฝํŠธ watch https://www.npmjs๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ 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

์ด์ œ ์ด๊ฒƒ์„ module.exports ๋Œ€ํ•œ ํ•จ์ˆ˜๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ ("User"๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ”๊พธ๊ณ  UserSchema๋ฅผ Schema์— ๋Œ€ํ•œ ์ธ์ˆ˜๋กœ ๋Œ€์ฒด) ํ•„์š”ํ•  ๋•Œ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

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์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ ์ˆ˜๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ๊ฐ€์žฅ ํšจ์œจ์ ์ด๊ณ  ์šฐ์•„ํ•˜๋ฉฐ ์ดํ•ดํ•˜๊ธฐ ์‰ฌ์šด ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์€ ํ…Œ์ŠคํŠธ ์ œํ’ˆ๊ตฐ ์™ธ๋ถ€์— ์—ฐ๊ฒฐ, ์Šคํ‚ค๋งˆ ๋ฐ ๋ชจ๋ธ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ฝ”๋“œ๋Š” ๊ฐ ํ…Œ์ŠคํŠธ ์ „์— ๋ชจ๋ธ์„ ์„ค์ •ํ•˜๋Š” ๋‹ค๋ฅธ ์˜ˆ์™€ ๋น„๊ตํ•  ๋•Œ ๋งค์šฐ DRY์ž…๋‹ˆ๋‹ค(์ €์—๊ฒŒ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Œ).

๋‹ค์Œ ํ…Œ์ŠคํŠธ ๋ชจ์Œ์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

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();
      });
  });
});

ํ–‰๋ณตํ•œ ๋ชฝ๊ณ ๋”ฉ๋น™.

์ด ์ฝ”๋“œ๋Š” ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

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 ๋“ฑ๊ธ‰