如何让 Jest 看到我为 MongoDB Stitch 编写的函数?
How to get Jest to see the functions I am writing for MongoDB Stitch?
我正在试用 Stitch,这是来自 MongoDB 的 serverless/hosted JavaScript 环境。我的主要目的是帮助我学习现代JavaScript,但我也在尝试编写一个有用的应用程序。
我编写了以下功能,并将其保存在我的 Stitch 应用程序中。我相信这遵循了在 Stitch 中编写函数的记录方式,并且我已经从 Stitch 管理控制台对其进行了测试:
exports = function(query){
const http = context.services.get("HTTP");
const urlBase = context.values.get("WhosebugApiUrl");
const options = [
'order=desc',
'sort=activity',
'site=Whosebug',
'q=' + encodeURIComponent(query),
'user=472495',
'filter=!--uPQ.wqQ0zW'
];
return http
.get({ url: urlBase + '?' + options.join('&') })
.then(response => {
// The response body is encoded as raw BSON.Binary. Parse it to JSON.
const ejson_body = EJSON.parse(response.body.text());
return ejson_body.total;
});
};
这段代码非常简单 - 它获取一个 http
对象用于进行外部 API 获取,并获取一个 URL urlBase
的配置值以联系 (解析为 https://api.stackexchange.com/2.2/search/excerpts
),然后调用堆栈溢出数据 API。这将针对我的用户和 returns 结果数运行搜索查询。
到目前为止一切顺利。现在,我想在 Jest 中本地调用这个函数。为此,我在本地 Docker 容器中安装了 Node 和 Jest,并编写了以下测试函数:
const callApi = require('./source');
test('Simple fetch with no user', () => {
expect(callApi('hello')).toBe(123);
});
失败,出现以下错误:
~ # jest
FAIL functions/callApi/source.test.js
✕ Simple fetch with no user (3ms)
● Simple fetch with no user
TypeError: callApi is not a function
2 |
3 | test('Simple fetch with no user', () => {
> 4 | expect(callApi('hello')).toBe(123);
| ^
5 | });
6 |
at Object.<anonymous>.test (functions/callApi/source.test.js:4:12)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.418s
Ran all test suites.
(事实上我预计它会失败,因为它包含一个 Jest 无法访问的全局对象 context
。我稍后会弄清楚如何模拟它,但现在 Jest 甚至不能完全看函数)。
我想我能看出原因 - 在 Jest 介绍文档中,必须为 SUT 执行此操作:
module.exports = function() { ... }
但是 Stitch 文档似乎要求将函数定义为:
exports = function() { ... }
我没有 JavaScript 的背景,无法理解其中的区别。我可以在 Stitch 中尝试 module.exports
,但我宁愿不这样做,因为这要么现在不起作用,要么在将来导致损坏。可以指示 Jest "see" 在没有 module
前缀的情况下裸露 exports
吗?
顺便说一下,我选择 Jest 是因为它很受欢迎,而且我的一些 JavaScript 同事也支持它。然而,我并不拘泥于它,如果已知它对 Stitch 开发更好,我会很乐意使用其他东西。
更新
根据下面来自 jperl 的有用答案,我发现以下构造在 Stitch 中是不可能的:
module.exports = exports = function() {}
我也做不到:
exports = function() {}
module.exports = exports
如果我尝试其中之一,我会收到以下错误:
runtime error during function validation
所以看起来我必须让 Jest 在没有 module.exports
的情况下工作,或者创建一个将 exports
版本导入 module.exports
的胶水文件,并使用主文件由 Stitch 开发,Jest 使用胶水导入器。
我建议您阅读这篇文章 thread。你认为它与 modules.exports
和 exports
有关是正确的。问题是 module.exports
和 exports
首先指向同一件事。所以像这样的东西有效:
//modify the same object that modules.exports is pointing to
exports.a = {}
exports.b = {}
但这不会:
exports = {}
为什么?因为现在 exports
指向 module.exports
以外的东西,所以你所做的根本没有效果。
更新
根据评论的一些更新,我们认为 Stitch 似乎不支持 Jest 要求的导出格式。
这是 jperl 回答的附录,展示了我如何在尊重 Stitch 的限制的同时让 Jest 工作。
首先,值得注意的是 Stitch 应用程序的布局方式。这是由 import/export 格式决定的。
auth_providers/
functions/
function_name_1/
config.json
source.js
function_name_2/
config.json
source.js
...
services/
values/
config.json
文件由Stitch远程创建,通过导出获取。这包含 ID 信息以唯一标识同一文件夹中的函数。
我相信 JavaScript 将测试与源代码混合在一起是很常见的做法,所以我遵循这种风格(我是现代 JS 的新手,我承认我觉得这种风格不整洁,但我 运行 尽管如此)。因此,我在每个函数文件夹中添加了一个 source.test.js
文件。
最后,由于Stitch需要的和Jest需要的不一致,我写了一个脚本在每个函数文件夹_source.js
下创建一个源代码文件。
因此,每个文件夹将包含这些文件(下划线文件可能会被 Git 忽略,因为它们将始终生成):
_source.js
config.json
source.js
source.test.js
为了创建带下划线的副本,我正在使用这个 shell 脚本:
#!/bin/bash
# Copy all source.js files as _source.js
for f in $(find functions/ -name source.js); do cp -- "$f" "$(dirname $f)/_$(basename $f)"; done
# Search and replace in all _source.js files
for f in $(find functions/ -name _source.js); do sed -i -e 's/exports =/module.exports =/g' $f; done
也许有点老套,但它确实有效!
我正在试用 Stitch,这是来自 MongoDB 的 serverless/hosted JavaScript 环境。我的主要目的是帮助我学习现代JavaScript,但我也在尝试编写一个有用的应用程序。
我编写了以下功能,并将其保存在我的 Stitch 应用程序中。我相信这遵循了在 Stitch 中编写函数的记录方式,并且我已经从 Stitch 管理控制台对其进行了测试:
exports = function(query){
const http = context.services.get("HTTP");
const urlBase = context.values.get("WhosebugApiUrl");
const options = [
'order=desc',
'sort=activity',
'site=Whosebug',
'q=' + encodeURIComponent(query),
'user=472495',
'filter=!--uPQ.wqQ0zW'
];
return http
.get({ url: urlBase + '?' + options.join('&') })
.then(response => {
// The response body is encoded as raw BSON.Binary. Parse it to JSON.
const ejson_body = EJSON.parse(response.body.text());
return ejson_body.total;
});
};
这段代码非常简单 - 它获取一个 http
对象用于进行外部 API 获取,并获取一个 URL urlBase
的配置值以联系 (解析为 https://api.stackexchange.com/2.2/search/excerpts
),然后调用堆栈溢出数据 API。这将针对我的用户和 returns 结果数运行搜索查询。
到目前为止一切顺利。现在,我想在 Jest 中本地调用这个函数。为此,我在本地 Docker 容器中安装了 Node 和 Jest,并编写了以下测试函数:
const callApi = require('./source');
test('Simple fetch with no user', () => {
expect(callApi('hello')).toBe(123);
});
失败,出现以下错误:
~ # jest
FAIL functions/callApi/source.test.js
✕ Simple fetch with no user (3ms)
● Simple fetch with no user
TypeError: callApi is not a function
2 |
3 | test('Simple fetch with no user', () => {
> 4 | expect(callApi('hello')).toBe(123);
| ^
5 | });
6 |
at Object.<anonymous>.test (functions/callApi/source.test.js:4:12)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.418s
Ran all test suites.
(事实上我预计它会失败,因为它包含一个 Jest 无法访问的全局对象 context
。我稍后会弄清楚如何模拟它,但现在 Jest 甚至不能完全看函数)。
我想我能看出原因 - 在 Jest 介绍文档中,必须为 SUT 执行此操作:
module.exports = function() { ... }
但是 Stitch 文档似乎要求将函数定义为:
exports = function() { ... }
我没有 JavaScript 的背景,无法理解其中的区别。我可以在 Stitch 中尝试 module.exports
,但我宁愿不这样做,因为这要么现在不起作用,要么在将来导致损坏。可以指示 Jest "see" 在没有 module
前缀的情况下裸露 exports
吗?
顺便说一下,我选择 Jest 是因为它很受欢迎,而且我的一些 JavaScript 同事也支持它。然而,我并不拘泥于它,如果已知它对 Stitch 开发更好,我会很乐意使用其他东西。
更新
根据下面来自 jperl 的有用答案,我发现以下构造在 Stitch 中是不可能的:
module.exports = exports = function() {}
我也做不到:
exports = function() {}
module.exports = exports
如果我尝试其中之一,我会收到以下错误:
runtime error during function validation
所以看起来我必须让 Jest 在没有 module.exports
的情况下工作,或者创建一个将 exports
版本导入 module.exports
的胶水文件,并使用主文件由 Stitch 开发,Jest 使用胶水导入器。
我建议您阅读这篇文章 thread。你认为它与 modules.exports
和 exports
有关是正确的。问题是 module.exports
和 exports
首先指向同一件事。所以像这样的东西有效:
//modify the same object that modules.exports is pointing to
exports.a = {}
exports.b = {}
但这不会:
exports = {}
为什么?因为现在 exports
指向 module.exports
以外的东西,所以你所做的根本没有效果。
更新
根据评论的一些更新,我们认为 Stitch 似乎不支持 Jest 要求的导出格式。
这是 jperl 回答的附录,展示了我如何在尊重 Stitch 的限制的同时让 Jest 工作。
首先,值得注意的是 Stitch 应用程序的布局方式。这是由 import/export 格式决定的。
auth_providers/
functions/
function_name_1/
config.json
source.js
function_name_2/
config.json
source.js
...
services/
values/
config.json
文件由Stitch远程创建,通过导出获取。这包含 ID 信息以唯一标识同一文件夹中的函数。
我相信 JavaScript 将测试与源代码混合在一起是很常见的做法,所以我遵循这种风格(我是现代 JS 的新手,我承认我觉得这种风格不整洁,但我 运行 尽管如此)。因此,我在每个函数文件夹中添加了一个 source.test.js
文件。
最后,由于Stitch需要的和Jest需要的不一致,我写了一个脚本在每个函数文件夹_source.js
下创建一个源代码文件。
因此,每个文件夹将包含这些文件(下划线文件可能会被 Git 忽略,因为它们将始终生成):
_source.js
config.json
source.js
source.test.js
为了创建带下划线的副本,我正在使用这个 shell 脚本:
#!/bin/bash
# Copy all source.js files as _source.js
for f in $(find functions/ -name source.js); do cp -- "$f" "$(dirname $f)/_$(basename $f)"; done
# Search and replace in all _source.js files
for f in $(find functions/ -name _source.js); do sed -i -e 's/exports =/module.exports =/g' $f; done
也许有点老套,但它确实有效!