【问题标题】:How to test a function which consumes a callback? Or how to defer the assertion?如何测试使用回调的函数?或者如何推迟断言?
【发布时间】:2017-06-09 21:37:38
【问题描述】:

我使用 Jest 来测试一个生成 JSON Web Token 的函数。好像我不能断言这个值,因为当我断言时,回调还没有被执行。

const issueJWT = function issueJWT(req, res, next) {
    jwt.sign(signUser, function (err, token) {
        if (err) {
            next(err);
            return;
        }
        res.locals.token = token;
        next();
    });
};

这是我的测试,我模拟请求和响应,然后断言结果:

test('Should return a JWT with proper value if nothing wrong happened', () => {
    issueJWT(request, response, mockNext);

    const JWT = response.locals.token;
    const tokenPayload = jwt.decode(JWT, { complete: true }).payload;
    expect(tokenPayload).toHaveProperty('iat');
    expect(tokenPayload).toHaveProperty('exp');
    expect(tokenPayload).toHaveProperty('id');
});

错误是:

TypeError:无法读取 null 的属性“有效负载”

如何让它发挥作用? 据我所知,我认为回调在任务队列中 意味着它将在事件循环中没有任何内容时执行,对吗?我想找到一种方法来推迟我的断言,但不知道如何......

感谢您的提示,我使用done,现在测试可以通过,但问题是,每当出现问题时,错误消息没有任何意义...我的解决方案有问题吗?

test('Should return a JWT with proper value if nothing wrong happened',  (done) => {
    const callback = () => {
        const JWT = response.locals.token;
        const tokenPayload = jwt.decode(JWT, { complete: true }).payload;

        expect(tokenPayload).toHaveProperty('iat');
        expect(tokenPayload).toHaveProperty('exp');
        expect(tokenPayload).toHaveProperty('id');
        expect(tokenPayload).toHaveProperty('iss');
        done();
    };

    issueJWT(request, response, callback);
});

现在的错误是:

超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调。

【问题讨论】:

  • 公平地说,@FelixKling,如果您使用回调而不是承诺,那么这些文档就不是很好。
  • @Paul:我不确定我是否理解。你到底是什么意思?
  • @FelixKling 我的意思是我很笨,阅读文档太快,完全跳过了回调块。 :P。尽管这是一个有趣的案例,因为在这种情况下 Mocha 和 Jest 使用的“完成”模式并不真正适用,因为回调模式假设您正在测试将回调公开为参数的函数。我看得出来他会很困惑。
  • @FelixKling 谢谢。阅读该文档并添加完成,现在可以使用。但不知何故,错误消息是不正确的......对此有什么提示吗?

标签: javascript unit-testing testing jestjs


【解决方案1】:

好的,在@felixKling 的帮助下让我真正阅读文档,您需要执行以下操作:

test('Should return a JWT with proper value if nothing wrong happened', done => {
    issueJWT(request, response, (e) => {
        const JWT = response.locals.token;
        const tokenPayload = jwt.decode(JWT, { complete: true }).payload;
        expect(tokenPayload).toHaveProperty('iat');
        expect(tokenPayload).toHaveProperty('exp');
        expect(tokenPayload).toHaveProperty('id');
        done();
    });
});

我不在我的开发盒上,所以我无法对此进行测试,但基本上这个想法是您使用测试回调的“完成”参数来表示测试正在等待异步代码。测试框架基本上会等待您的测试在退出之前调用该回调。

在这种情况下,来自issueJWTnext() 调用是我们在检查各种对象是否已更新之前等待触发的内容。如果您没有在中间件中使用next(),您可能需要模拟您调用的任何响应方法(例如response.end())来进行测试。

【讨论】:

  • 谢谢,现在终于得到结果了,新的问题是错误信息与我的问题无关...有什么提示吗?
  • 您真的应该对此提出另一个问题。但通常这就是错误所说的;测试花费的时间超过了默认的超时间隔。这意味着要么增加间隔,要么查看您的管道以确保您实际上在所有代码分支中调用回调。
猜你喜欢
  • 2016-07-08
  • 2014-01-27
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 2013-08-03
  • 2018-11-15
  • 2022-01-24
相关资源
最近更新 更多