单元测试环回模型
Unit testing Loopback models
使用 Loopback,我们创建了一些自定义远程方法,我们想要对该逻辑进行单元测试。我想要完成的是只加载一个模型,而不是我们所有的模型,并对那个模型的自定义远程方法进行单元测试。
我们可以将这个模型连接到内存数据库(在我们的例子中不是 Postgres),但是我需要以某种方式告诉 Loopback 这个孤立的模型,而不使用 Loopback 引导。 (如果我们使用标准的 Loopback 引导(app.boot()),它将加载我们所有的模型和整个 shebang,我认为我们应该避免出于隔离目的)。
我们在正在进行的单元测试中进行了此设置:
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();
}
});
});
所以我不想使用 Loopback 引导,而是想加载模型架构和模型逻辑,然后以隔离的方式将其附加到 Loopback 应用程序。
是否有我们可以使用的环回调用,将此模型附加到环回 server/app?
我正在寻找这种类型的电话:
app.useModel(Contact);
基本上我想要做的是这样的:
app.models.Contact = Contact;
但这绝对是错误的做法 - 只是在寻找正确的 API 调用。
也许这是正确的决定?
Contact.attachTo(loopback.memory());
免责声明:我是 LoopBack 维护者,也是 loopback-boot@2 的原作者
设置模型的规范方法(也被 loopback-boot 在后台使用)是调用 app.registry.createModel(json)
然后 app.model(ModelCtor, config)
。
在您的具体情况下:
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();
}
});
});
我发现这种方法有两个可能的注意事项:
- 如果您的自定义远程方法正在访问 other/related 模型,则此设置将失败,因为这些模型不可用。
- 您的服务器没有在
server/middleware.json
中配置任何中间件,也没有从启动脚本中添加任何其他内容。
我个人建议您尝试使用 loopback-boot,但要覆盖 dataSources 和要在应用程序中配置的模型列表。大致如下:
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'
}
},
});
之所以可行,是因为 loopback-boot 延迟加载模型,即仅在应用程序及其父项中配置的模型。
使用 Loopback,我们创建了一些自定义远程方法,我们想要对该逻辑进行单元测试。我想要完成的是只加载一个模型,而不是我们所有的模型,并对那个模型的自定义远程方法进行单元测试。
我们可以将这个模型连接到内存数据库(在我们的例子中不是 Postgres),但是我需要以某种方式告诉 Loopback 这个孤立的模型,而不使用 Loopback 引导。 (如果我们使用标准的 Loopback 引导(app.boot()),它将加载我们所有的模型和整个 shebang,我认为我们应该避免出于隔离目的)。
我们在正在进行的单元测试中进行了此设置:
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();
}
});
});
所以我不想使用 Loopback 引导,而是想加载模型架构和模型逻辑,然后以隔离的方式将其附加到 Loopback 应用程序。
是否有我们可以使用的环回调用,将此模型附加到环回 server/app?
我正在寻找这种类型的电话:
app.useModel(Contact);
基本上我想要做的是这样的:
app.models.Contact = Contact;
但这绝对是错误的做法 - 只是在寻找正确的 API 调用。
也许这是正确的决定?
Contact.attachTo(loopback.memory());
免责声明:我是 LoopBack 维护者,也是 loopback-boot@2 的原作者
设置模型的规范方法(也被 loopback-boot 在后台使用)是调用 app.registry.createModel(json)
然后 app.model(ModelCtor, config)
。
在您的具体情况下:
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();
}
});
});
我发现这种方法有两个可能的注意事项:
- 如果您的自定义远程方法正在访问 other/related 模型,则此设置将失败,因为这些模型不可用。
- 您的服务器没有在
server/middleware.json
中配置任何中间件,也没有从启动脚本中添加任何其他内容。
我个人建议您尝试使用 loopback-boot,但要覆盖 dataSources 和要在应用程序中配置的模型列表。大致如下:
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'
}
},
});
之所以可行,是因为 loopback-boot 延迟加载模型,即仅在应用程序及其父项中配置的模型。