【问题标题】:How to get Jest to see the functions I am writing for MongoDB Stitch?如何让 Jest 看到我为 MongoDB Stitch 编写的函数?
【发布时间】:2019-12-23 03:50:51
【问题描述】:

我正在试用 Stitch,这是一个来自 MongoDB 的无服务器/托管 JavaScript 环境。我的主要目的是帮助我学习现代 JavaScript,但我也在尝试编写一个有用的应用程序。

我编写了以下函数,并将其保存在我的 Stitch 应用程序中。我相信这遵循了在 Stitch 中编写函数的文档化方式,并且我已经从 Stitch 管理控制台对其进行了测试:

exports = function(query){
  const http = context.services.get("HTTP");
  const urlBase = context.values.get("stackOverflowApiUrl");
  const options = [
    'order=desc',
    'sort=activity',
    'site=stackoverflow',
    '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。这将对我的用户运行搜索查询并返回结果数。

到目前为止一切顺利。现在,我想在 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 在没有 module 前缀的情况下“看到”裸露的 exports 吗?

顺便说一句,我之所以选择 Jest,是因为它很流行,而且我的一些 JavaScript 同事也支持它。但是,我并不喜欢它,如果已知它更适合 Stitch 开发,我很乐意使用其他东西。

更新

根据下面 jperl 的有用答案,我发现在 Stitch 中无法进行以下构造:

module.exports = exports = function() {}

我也不能这样做:

exports = function() {}
module.exports = exports

如果我尝试任何一个,我都会收到以下错误:

函数验证期间的运行时错误

所以看起来我必须让 Jest 在没有module.exports 的情况下工作,或者创建一个胶水文件,将exports 版本导入module.exports,主文件由 Stitch 使用,胶水导入器是被 Jest 使用。

【问题讨论】:

    标签: javascript jestjs mongodb-stitch


    【解决方案1】:

    我建议您阅读此thread。而且您认为它与modules.exportsexports 有关是对的。问题是module.exportsexports 首先指向同一个东西。所以像这样的工作:

    //modify the same object that modules.exports is pointing to
    exports.a = {}
    exports.b = {}
    

    但这不会:

    exports = {}
    

    为什么?因为现在exports 指向的不是module.exports,所以你所做的完全没有效果。

    更新

    随着 cmets 的一些更新,我们发现 Stitch 似乎不支持 Jest 所需的导出格式。

    【讨论】:

    • 啊,谢谢 jperl!我想知道我的问题是否与您的链接问题足够接近,我想知道它是否可以称为重复。老实说,我期待答案是 Stitch 中特定于实现的奇怪之处,并且鉴于 Stitch 在 Stack Overflow 上是一个鲜为人知的野兽,我认为不可能已经存在答案。
    • “因为现在 export 指向的是 module.exports 以外的其他东西,所以你正在做的事情根本没有效果”——确实,但 Stitch 仍然可以导入它。我想知道这是不是因为exports是在Stich环境中本地读取的,而不是被require获取的?
    • 我已更新问题以解释 Stitch 不接受 module.exports。有没有什么方法可以让 Jest 使用裸 exports,而不是我编写一个测试引导程序来“预编译”测试以包含 module. 前缀?
    • @halfer 哦,有趣!这是一个特殊的案例。我猜这个模块根本没有定义,exports 也不是 module.exports 的别名。
    • @halfer 你能试试添加if (!module) module = {}; module.exports = exports吗?
    【解决方案2】:

    这是 jperl 答案的附录,以展示我如何在尊重 Stitch 限制的同时让 Jest 工作。

    首先,值得注意的是 Stitch 应用程序的布局方式。这是由导入/导出格式决定的。

    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
    

    也许有点hacky,但它有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-24
      • 2021-08-06
      • 2019-02-01
      • 1970-01-01
      • 2021-12-03
      相关资源
      最近更新 更多