私が作成した反応コンポーネントのテストを、そのようなメソッド内でnavigator.geolocation.getCurrentPosition()
を使用して記述しようとしています(コンポーネントの大まかな例):
class App extends Component {
constructor() {
...
}
method() {
navigator.geolocation.getCurrentPosition((position) => {
...code...
}
}
render() {
return(...)
}
}
テストを含む create-react-app を使用しています:
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
});
このテストは失敗し、これをコンソールに出力します。
TypeError: Cannot read property 'getCurrentPosition' of undefined
私はReactは初めてですが、angular 1.xでかなりの経験があります。angularで、モックアウトすることは一般的です(テスト内でbeforeEach)関数、「サービス」、およびnavigator.geolocation.etcなどのグローバルオブジェクトメソッドで、この問題の調査に時間を費やし、このコードのコードはモックに到達できる最も近いものです。
global.navigator = {
geolocation: {
getCurrentPosition: jest.fn()
}
}
これをAppのテストファイルに入れましたが、効果がありませんでした。
このナビゲーターメソッドを「モック」してテストに合格させるにはどうすればよいですか?
編集:私は geolocation と呼ばれるライブラリの使用を検討しましたが、これはおそらくnavigator.getCurrentPosition
をラップしてノード環境で使用するためのものです。私が正しく理解していれば、jestはノード環境でテストを実行し、JSDOMを使用してwindow
などのモックアウトを作成します。 JSDOMによるnavigator
のサポートについて、多くの情報を見つけることができませんでした。上記のライブラリは私の反応アプリで動作しませんでした。特定のメソッドgetCurrentPositionを使用すると、ライブラリ自体が正しくインポートされ、Appクラスのコンテキスト内で利用可能であっても、未定義のみが返されます。
global.navigator
オブジェクトはすでに存在しているようです。あなたと同じように、オブジェクトを再割り当てできませんでした。
ジオロケーションパーツをモックして既存のglobal.navigator
に追加するとうまくいくことがわかりました。
const mockGeolocation = {
getCurrentPosition: jest.fn(),
watchPosition: jest.fn()
};
global.navigator.geolocation = mockGeolocation;
ここに記載されているように、これをsrc/setupTests.js
ファイルに追加しました- https://create-react-app.dev/docs/running-tests#initializing-test-environment
この問題は解決されたかもしれませんが、少なくとも私にとっては、上記のすべての解決策がすべて間違っているようです。
このモックを実行すると、getCurrentPosition: jest.fn()
は未定義を返します。何かを返したい場合は、これが正しい実装です。
const mockGeolocation = {
getCurrentPosition: jest.fn()
.mockImplementationOnce((success) => Promise.resolve(success({
coords: {
latitude: 51.1,
longitude: 45.3
}
})))
};
global.navigator.geolocation = mockGeolocation;
私はcreate-react-appを使用しています
setupFiles
によるモック
// __mocks__/setup.js
jest.mock('Geolocation', () => {
return {
getCurrentPosition: jest.fn(),
watchPosition: jest.fn(),
}
});
そしてあなたのpackage.json
"jest": {
"preset": "react-native",
"setupFiles": [
"./__mocks__/setup.js"
]
}
何らかの理由で、global.navigatorオブジェクトを定義しなかったため、setupTests.jsファイルで指定する必要がありました
const mockGeolocation = {
getCurrentPosition: jest.fn(),
watchPosition: jest.fn(),
}
global.navigator = { geolocation: mockGeolocation }
enzyme を使用してしまいました。私のテストは次のようになります:
import React from 'react'
import App from './App'
import {shallow} from 'enzyme'
it('renders without crashing', () => {
const app = shallow(<App />)
expect(app).toBeDefined()
});
enzyme
パッケージとreact-addons-test-utils
パッケージの両方を追加する必要がありました。設定は必要ありません。現時点では、酵素がどのように機能するかよく知らないので、なぜこれが問題を解決したのか実際にはわかりません。私はそれがEnzymeのREADMEからのこの行と関係があると思います:
EnzymeのAPIは、jQueryのAPIを模倣してDOMの操作とトラバーサルを行うことにより、直感的で柔軟なものにすることを目的としています。