gpt4 book ai didi

javascript - promise 未在 Jest 测试中执行

转载 作者:行者123 更新时间:2023-11-29 23:22:26 27 4
gpt4 key购买 nike

我目前正在为我们的一个项目创建一个新的 React 组件,但我几乎无法为它编写适当的测试。我已经阅读了很多文档和博客文章等等,但我似乎无法运行它。

长话短说

对我来说,Promise 似乎没有执行。当我使用调试器运行测试时,它不会在 Promise 的函数中停止,也不会在 then() 函数中停止。但是,它将在测试本身的 then/catch 函数中停止。

代码

因此,该组件实际上相当简单。目前它应该通过 API 搜索位置。它的测试看起来像这样:

import axios from 'axios';
import React from 'react';
import {shallowWithIntl} from "../../../Helpers/react-intl-helper";
import Foo from "../../../../src/Components/Foo/Foo";
import {mount} from "enzyme";

const queryTerm = 'exampleQueryTerm';
const locationAgs = 'exampleLocationKey';

const fakeLocationObject = {
search: '?for=' + queryTerm + '&in=' + locationAgs
};

jest.mock('axios', () => {
const exampleLocations = [{
data: {"id": "expected-location-id"}
}];

return {
get: jest.fn().mockReturnValue(() => {
return Promise.resolve(exampleLocations)
})
};
});

let fooWrapper, instance;

beforeEach(() => {
global.settings = {
"some-setting-key": "some-setting-value"
};

global.URLSearchParams = jest.fn().mockImplementation(() => {
return {
get: function(param) {
if (param === 'for') return queryTerm;
else if (param === 'in') return locationAgs;
return '';
}
}
});

fooWrapper = shallowWithIntl(<Foo location={fakeLocationObject} settings={ global.settings } />).dive();
instance = fooWrapper.instance();
});

it('loads location and starts result search', function() {
expect.assertions(1);

return instance
.searchLocation()
.then((data) => {
expect(axios.get).toHaveBeenCalled();
expect(fooWrapper.state('location')).not.toBeNull();
})
.catch((error) => {
expect(fooWrapper.state('location')).toBe(error);
});
});

因此,如您所见,测试应该在 Foo 组件实例上调用 searchLocation,它返回一个 Promise 对象,正如您(几乎)在其实现中看到的那样。

import React, { Component } from 'react';
import { injectIntl } from "react-intl";
import {searchLocationByKey} from "../../Services/Vsm";

class Foo extends Component {

constructor(props) {
super(props);

this.state = {
location: null,
searchingLocation: false,
searchParams: new URLSearchParams(this.props.location.search)
};
}

componentDidUpdate(prevProps) {
if (!prevProps.settings && this.props.settings) {
this.searchLocation();
}
}

searchLocation() {
this.setState({
searchingLocation: true
});

const key = this.state.searchParams.get('in');

return searchLocationByKey(key)
.then(locations => {
this.setState({ location: locations[0], searchingLocation: false })
})
.catch(error => console.error(error));
}

render() {
// Renders something
};

}

export default injectIntl(Foo);

输入searchLocationByKey:

function requestLocation(url, resolve, reject) {
axios.get(url).then(response => {
let locations = response.data.map(
location => ({
id: location.collectionKey || location.value,
rs: location.rs,
label: location.label,
searchable: location.isSearchable,
rawData: location
})
);

resolve(locations);
}).catch(error => reject(error));
}

export const searchLocationByKey = function(key) {
return new Promise((resolve, reject) => {
let url = someGlobalBaseUrl + '?regional_key=' + encodeURIComponent(key);
requestLocation(url, resolve, reject);
});
};

问题

这是测试的输出:

Error: expect(received).toBe(expected)

Expected value to be (using ===):
[Error: expect(received).not.toBeNull()

Expected value not to be null, instead received
null]
Received:
null

我必须承认,我对 Promises、React 和 JavaScript 测试还很陌生,所以我可能混淆了几件事。正如我上面所写的,Promise 似乎没有正确执行。调试时不会停在Foo.searchLocation中定义的then()函数中。相反,显然,测试中定义的 then() 和 catch() 函数都被执行了。

我已经在这个问题上花了太多时间,但我对如何继续下去一无所知。我做错了什么?

更新 1:done() 函数

正如 El Aoutar Hamza 在下面的回答中指出的那样,可以将一个函数(通常称为“完成”)传递给测试函数。我正是这样做的:

it('loads location and starts result search', function(done) {
expect.assertions(1);

return instance
.searchLocation()
.then((data) => {
expect(fooWrapper.state('location')).not.toBeNull();
done();
})
.catch((error) => {
expect(fooWrapper.state('location')).toBe(error);
});
});

但我最终得到了这个错误:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

最佳答案

requestLocation 中,您正在尝试访问 response.data,并且在模拟 axios.get 时,您将返回一个已解决的 Promise 数组 !你应该返回一个 Promise 解决了一个 object with data property (that contains the array).

jest.mock('axios', () => ({
get: jest.fn(() => Promise.resolve({
data: [{ "id": "expected-location-id" }]
}))
}));

另一点是,在测试异步代码时,测试甚至会在调用回调之前完成,这就是为什么您应该考虑为您的测试提供一个名为 done 的参数。 , 那样的话,jest 会等到 done 回调被调用。

describe('Foo', () => {
it('loads location and starts result search', done => {
expect.assertions(1);

return instance
.searchLocation()
.then((data) => {
expect(fooWrapper.state('location')).not.toBeNull();
done();
})
.catch((error) => {
expect(fooWrapper.state('location')).toBe(error);
done();
});
});
});

关于javascript - promise 未在 Jest 测试中执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50200523/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com