Jest - 嵌套承诺断言永不归来

时间:2018-05-07 01:57:18

标签: javascript jestjs

我目前正在尝试使用Jest进行实时API测试。也许有一个更好的工具,但我想这是另一个讨论。我遇到了一个问题,虽然Jest在第二个promise中包含错误时返回错误:Expected one assertion to be called but received zero assertion calls.。我认为Jest会支持承诺嵌套,但它似乎没有按预期运行。似乎断言没有被退回。这种语法适用于单个承诺。

我正在使用Jest V22.4.3和Node V8.9.4。

新ticket.test.js

const call = require('../resources/call');

test('Create a new, valid ticket.', () => {
    expect.assertions(1);

    return call.makePostRequest(~login-url~, {
        'username': 'xxxxx',
        'password': 'xxxxx',
        'version': 'xxxxx'
    }).then((response) => {
        call.makePostRequest(~ticket-url~, {
            'inInvType': 1,
            'inRetailOrClearance': 'R',
            'inAction': 'L',
            'inToken': response.token
        }).then((response) => {
            expect(response.retVal).toBe('0');
        });
    });
});

call.js

const https = require('https');

function makePostRequest(subURL, payload) {
    let options,
        request,
        body;

    // Convert our payload to JSON string.
    payload = JSON.stringify(payload);

    // Build our request options configuration.
    options = {
        hostname: ~base-url~,
        port: 8443,
        "rejectUnauthorized": false,
        path: subURL,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Accept': '*/*'
        },
        observe: 'body',
        responseType: 'json',
        reportProgress: true,
        withCredentials: false
    };

    body = '';

    return new Promise((resolve) => {
        request = https.request(options, (response) => {

            // Collect our response data as it streams in.
            response.on('data', (data) => {
                body += data;
            });

            // Once ended, resolve with data.
            response.on('end', () => {
                body = JSON.parse(body);
                resolve(body);
            });
        });

        request.on('error', (err) => {
            resolve(err)
        });

        request.write(payload);
        request.end();
    });
}

module.exports.makePostRequest = makePostRequest;

3 个答案:

答案 0 :(得分:1)

测试如何知道测试用例何时完成?

在您的测试用例中返回Promise是正确的想法,但是当您请求票证URL时,您的承诺链接会中断。尝试从该请求中返回Promise。

const call = require('../resources/call');

test('Create a new, valid ticket.', () => {
    expect.assertions(1);

// => Returning the promise is the right idea but ...
    return call.makePostRequest(~login-url~, {
        'username': 'xxxxx',
        'password': 'xxxxx',
        'version': 'xxxxx'
    }).then((response) =>
// ... the inner block doesn't return anything.
// Without a Promise to signal there's async code running,
// Jest won't run this block. Try returning this call (delete the {})
        call.makePostRequest(~ticket-url~, {
            'inInvType': 1,
            'inRetailOrClearance': 'R',
            'inAction': 'L',
            'inToken': response.token
        }).then((response) => {
            expect(response.retVal).toBe('0');
        });
    );
});

如果您对async / await感到满意,那么您也可以使用它:

const call = require('../resources/call');

test('Create a new, valid ticket.', async () => {
    expect.assertions(1);

    let response = await call.makePostRequest(~login-url~, {
        'username': 'xxxxx',
        'password': 'xxxxx',
        'version': 'xxxxx',
    });

    response = await call.makePostRequest(~ticket-url~, {
        'inInvType': 1,
        'inRetailOrClearance': 'R',
        'inAction': 'L',
        'inToken': response.token,
    });

    expect(response.retVal).toBe('0');
});

答案 1 :(得分:0)

我不确定为什么会失败,但我建议扁平化你的承诺链,以便测试每一个单独的。

由于您使用了Jest和Node的非常现代版本,因此您可以使用async / await个关键字,因为它可以更清楚地了解实际情况发生并减轻了你必须自己进入的回调混乱。

这样的事情可以解决问题;

it('Create a new, valid ticket.', async () => {
    const res = await call.makePostRequest(~login-url~, {
        'username': 'xxxxx',
        'password': 'xxxxx',
        'version': 'xxxxx'
    });

    const response = await call.makePostRequest(~ticket-url~, {
        'inInvType': 1,
        'inRetailOrClearance': 'R',
        'inAction': 'L',
        'inToken': res.token
    });

    expect(response.retVal).toBe('0');
});

答案 2 :(得分:0)

看来我的问题与Jest完全无关,但我会在这里发布,以防其他人有类似的问题。在进行API调用时,我的Node脚本指向负载均衡器。在我的代码中,我首先打电话请求一个新的令牌。然后我在第二次调用中使用该令牌在后端创建一个新事务。问题是我们的一台服务器的时钟设置与另一台不同。所以,我会从“更快”的服务器收到令牌,然后有时负载均衡器将我引导到“较慢”的服务器。当我尝试在“较慢”的服务器上使用令牌时,它被认为是无效的,因为它是在将来发布的。

要解决此问题,我通过本教程启用了NTP:https://www.digitalocean.com/community/tutorials/how-to-set-up-time-synchronization-on-ubuntu-16-04