简体   繁体   English

单元测试环回模型

[英]Unit testing Loopback models

Using Loopback, we have created some custom remote methods, and we want to unit test that logic. 使用Loopback,我们创建了一些自定义远程方法,我们想要对该逻辑进行单元测试。 What I am looking to accomplish is to load just one model, not all our models, and unit test the custom remote method(s) for that one model. 我想要完成的是只加载一个模型,而不是我们所有的模型,并单元测试该模型的自定义远程方法。

We can connect this model to the memory database (instead of Postgres in our case), but somehow I need to tell Loopback about this isolated model, without using Loopback boot. 我们可以将这个模型连接到内存数据库(在我们的例子中不是Postgres),但不知怎的,我需要告诉Loopback这个孤立的模型,而不使用Loopback引导。 (If we use the standard Loopback boot (app.boot()), it will load all our models and the whole shebang, which I think we should avoid for isolation purposes). (如果我们使用标准的Loopback启动(app.boot()),它将加载我们所有的模型和整个shebang,我认为我们应该避免出于隔离目的)。

We have this setup in a unit test that is a work in progress: 我们在单元测试中进行了此设置,这是一项正在进行的工作:

  const supertest = require('supertest');

  //load the schema for the model
  const ContactSchema = require(path.resolve(projectRoot + '/server/models/contact.json'));

  const opts = {
    strict: true
  };

  const dataSource = loopback.createDataSource({
    connector: loopback.Memory
  });


  const Contact = dataSource.createModel('Contact', ContactSchema, opts);

  //load remote methods for this model
  require(path.resolve(projectRoot + '/server/models/contact.js'))(Contact);


  const app = loopback();


  this.it.cb('test contact', t => {

    supertest(app).get('/api/Contacts')
      .expect(200)
      .end(function (err, res) {
        if (err) {
          t.fail(err);    // we naturally get a 404, because the model hasn't been attached to this Loopback server
        }
        else {
          t.done();
        }
      });

  });

so instead of using Loopback boot, I want to load the model schema and model logic and then attach it to the Loopback app in an isolated way. 因此,我想加载模型架构和模型逻辑,然后以隔离的方式将其附加到Loopback应用程序,而不是使用Loopback启动。

Is there a Loopback call we can use, to attach this model to the Loopback server/app? 我们可以使用Loopback调用,将此模型附加到Loopback服务器/应用程序吗?

I am looking for this type of call: 我正在寻找这种类型的电话:

app.useModel(Contact);

Essentially what I am looking to do is something like this: 基本上我要做的是这样的事情:

app.models.Contact = Contact;

but that is definitely the wrong way to do it - just looking for the right API call. 但这绝对是错误的做法 - 只是寻找合适的API调用。

Perhaps this is the right call? 也许这是正确的电话?

Contact.attachTo(loopback.memory());

Disclaimer: I am a LoopBack maintainer and the original author of loopback-boot@2 免责声明:我是LoopBack维护者,也是loopback-boot @ 2的原作者

The canonical way of setting up a model (which is used by loopback-boot under the hood too) is to call app.registry.createModel(json) and then app.model(ModelCtor, config) . 设置模型的规范方法(也是由引擎盖下的loopback-boot使用)是调用app.registry.createModel(json)然后app.model(ModelCtor, config)

In your particular case: 在您的特定情况下:

const app = loopback();
// Consider using local per-app registry of models to avoid
// interference between tests. By default, all LoopBack apps
// share the same global registry (one per process)
// const app = loopback({ localRegistry: true });

// create in-memory datasources
app.dataSource('db', { connector: 'memory' });

//load the schema for the model
const ContactSchema = require(path.resolve(projectRoot + '/server/models/contact.json'));

const Contact = app.registry.createModel(ContactSchema);

//load remote methods for this model
require(path.resolve(projectRoot + '/server/models/contact.js'))(Contact);

// Caveat lector: the configuration may contain more than just dataSource,
// It may be safer to read the model configuration from "server/model-config"
// and override "dataSource" property.
app.model(Contact, { dataSource: 'db' });

// setup REST API
app.use('/api', loopback.rest());

// now we are good to start testing

const supertest = require('supertest');


this.it.cb('test contact', t => {

  supertest(app).get('/api/Contacts')
    .expect(200)
    .end(function (err, res) {
      if (err) {
        t.fail(err);    // we naturally get a 404, because the model hasn't been attached to this Loopback server
      }
      else {
        t.done();
      }
    });

});

I see two possible caveats with this approach: 我看到这种方法有两个可能的警告:

  • If your custom remote method is accessing other/related models, then it will fail in this setup, because those models are not available. 如果您的自定义远程方法正在访问其他/相关模型,则在此设置中将失败,因为这些模型不可用。
  • Your server does not have any middleware configured in server/middleware.json nor any other additions from boot scripts. 您的服务器没有在server/middleware.json middleware.json中配置任何中间件,也没有从引导脚本中添加任何其他server/middleware.json

I would personally recommend you to try using loopback-boot, but override dataSources and the list of models to be configured in the application. 我个人建议你尝试使用loopback-boot,但是覆盖dataSources和要在应用程序中配置的模型列表。 Something along the following lines: 以下内容:

const app = loopback();
boot(app, {
  appRootDir: path.resolve('../server'),
  env: 'unit-test',
  // Alternatively, the "dataSources" configuration for tests
  // can be provided in "server/datasources.unit-test.json"
  dataSources: {
    db: {
      connector: 'memory'
    }
  },
  models: {
    Contact: {
      // as I mentioned before, it's probably better to load this section
      // from "server/model-config.json"
      dataSource: 'db'
    }
  },
});

This works because loopback-boot loads models lazily, ie only models configured in the app and their parents. 这是有效的,因为loopback-boot会懒惰加载模型,即只在应用程序中配置的模型及其父项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM