tim*_*hym 13 unit-testing reactjs jestjs create-react-app
我正在尝试为我构建的反应组件编写测试,这些组件navigator.geolocation.getCurrentPosition()在类似的方法中使用(我的组件的粗略示例):
class App extends Component {
constructor() {
...
}
method() {
navigator.geolocation.getCurrentPosition((position) => {
...code...
}
}
render() {
return(...)
}
}
Run Code Online (Sandbox Code Playgroud)
我正在使用create-react-app,其中包括一个测试:
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});
Run Code Online (Sandbox Code Playgroud)
此测试失败,在控制台中打印出来:
TypeError: Cannot read property 'getCurrentPosition' of undefined
Run Code Online (Sandbox Code Playgroud)
我是React的新手,但对于角度1.x有相当多的经验.在angular中,通常模拟(在beforeEach中的测试中)函数,"服务"和全局对象方法,如navigator.geolocation.etc.我花了很多时间研究这个问题,这段代码是我最接近模拟的代码:
global.navigator = {
geolocation: {
getCurrentPosition: jest.fn()
}
}
Run Code Online (Sandbox Code Playgroud)
我把它放在App的测试文件中,但没有效果.
我如何"模拟"这个导航器方法并让测试通过?
编辑:我研究了一个名为geolocation的库,它应该包含navigator.getCurrentPosition在节点环境中使用.如果我理解正确,jest在节点环境中运行测试并使用JSDOM来模拟像window.我无法找到有关JSDOM支持的更多信息navigator.上面提到的库在我的反应应用程序中不起作用.使用特定方法getCurrentPosition只会返回undefined,即使库本身已正确导入并在App类的上下文中可用.
jar*_*e87 24
似乎已经有了一个global.navigator对象,和你一样,我无法重新分配它.
我发现嘲笑地理位置部分并将其添加到现有global.navigator工作中.
const mockGeolocation = {
getCurrentPosition: jest.fn(),
watchPosition: jest.fn()
};
global.navigator.geolocation = mockGeolocation;
Run Code Online (Sandbox Code Playgroud)
我把它添加到src/setupTests.js这里描述的文件中 - https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#initializing-test-environment
Mad*_*deo 11
我知道这个问题可能已经解决,但似乎上述所有解决方案都是错误的,至少对我而言.
当你这样做时:getCurrentPosition: jest.fn()
它返回undefined,如果你想返回一些东西,这是正确的实现:
const mockGeolocation = {
getCurrentPosition: jest.fn()
.mockImplementationOnce((success) => Promise.resolve(success({
coords: {
latitude: 51.1,
longitude: 45.3
}
})))
};
global.navigator.geolocation = mockGeolocation;
Run Code Online (Sandbox Code Playgroud)
我正在使用create-react-app
适合任何人的 TypeScript 版本
Cannot assign to 'geolocation' because it is a read-only property.
在mockNavigatorGeolocation.ts文件中(可以位于test-utils文件夹或类似文件夹中)
export const mockNavigatorGeolocation = () => {
const clearWatchMock = jest.fn();
const getCurrentPositionMock = jest.fn();
const watchPositionMock = jest.fn();
const geolocation = {
clearWatch: clearWatchMock,
getCurrentPosition: getCurrentPositionMock,
watchPosition: watchPositionMock,
};
Object.defineProperty(global.navigator, 'geolocation', {
value: geolocation,
});
return { clearWatchMock, getCurrentPositionMock, watchPositionMock };
};
Run Code Online (Sandbox Code Playgroud)
然后我将其导入到文件顶部的测试中:
import { mockNavigatorGeolocation } from '../../test-utils';
Run Code Online (Sandbox Code Playgroud)
然后像这样使用该函数:
const { getCurrentPositionMock } = mockNavigatorGeolocation();
getCurrentPositionMock.mockImplementation((success, rejected) =>
rejected({
code: '',
message: '',
PERMISSION_DENIED: '',
POSITION_UNAVAILABLE: '',
TIMEOUT: '',
})
);
Run Code Online (Sandbox Code Playgroud)
小智 5
与嘲笑 setupFiles
// __mocks__/setup.js
jest.mock('Geolocation', () => {
return {
getCurrentPosition: jest.fn(),
watchPosition: jest.fn(),
}
});
Run Code Online (Sandbox Code Playgroud)
然后在你的 package.json
"jest": {
"preset": "react-native",
"setupFiles": [
"./__mocks__/setup.js"
]
}
Run Code Online (Sandbox Code Playgroud)