モック-噛まないでください!
これらは、より単純で信頼性の高いテストを作成できるように設計されています。このシリーズの記事では、Reactコンポーネントをモック(または「スタブ」)するときに依存するパターンを紹介します。
これは、コンポーネントスタブの良い例です。私はを使用します
jest.mock
。これについては、以下で詳しく説明します。
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(() => (
<div data-testid="PostContent" />
))
}))
典型的なReactコンポーネントスタブはもっと複雑に見えるべきではありません。非常に単純なスタブ値(
div
)とdata-testid
、DOMでレンダリングされたインスタンスを非常に簡単に見つけることができる属性に注意してください。慣例により、使用されるテスト識別子はコンポーネント名と一致する必要があります。この場合はPostContent
です。
それらがどのように使用されるかを見る前に、まずモックとは何か、そしてなぜそれらを使用したいかを覚えておきましょう。
モックとは何ですか?
JavaScriptの世界では、モックという用語は、モックされた実装またはテストdoubleを指すために非常に広く使用されています。モックされた実装は、テストの実行中に本番コード内の他の実装を置き換える単なる値です。彼らは置き換えられるオブジェクトのインターフェースを試してみるので、コードの残りの部分は置き換えがなかったかのように機能します。
これを実行する理由はいくつかあります。それらを例を挙げて見ていきます。
モックされた実装について詳しく知りたい場合は、MartinFowlerの著書「MocksAreNotStubs 」をお読みください。
冗談とあざける
Jestには、
jest.mock
交換するモジュール全体をモックできる機能があります。このチュートリアルでは、この機能に焦点を当てましたが、JavaScriptでオブジェクトを置き換える方法は他にもあります。
『Mastering React Test-Driven Development』では、 ES6という名前のモジュールインポートを使用してテストダブルを作成しています。このアプローチはもう少し柔軟性を与えますが、もう少しハックっぽく見えます。
Jest jest.mock
モックはあなたのテストが速くて壊れにくいことを保証すると言います。
これは本当ですが、これは私がモックを使用する主な理由ではありません。
モックを使用するのは、テストを互いに独立させるのに役立つからです。
これが当てはまる理由を理解するために、例を見てみましょう。
なぜモキ?
以下は、
BlogPage
2つのことを実行するコンポーネントのリストです。id
プロパティからフェッチし、url
それを使用してPostContent
コンポーネントを表示しますid
。
const getPostIdFromUrl = url =>
url.substr(url.lastIndexOf("/") + 1)
export const BlogPage = ({ url }) => {
const id = getPostIdFromUrl(url)
return (
<PostContent id={id} />
)
}
このコンポーネントのテストを作成していて
BlogPage.test.js
、すべてのテストがに含まれていると想像してください。これは、コンポーネントBlogPage
とをカバーする単一のテストスイートですPostContent
。
この時点で、あなたはまだモックを必要はありません。私たちは見ていない
PostContent
、まだそれを、しかし、サイズを与えBlogPage
、実際には2つの別々のテストスイートを持っている必要がない、ので、BlogPage
それはだ、一般的にシンプルPostContent
。
ここで
BlogPage
、yとyの両方にPostContent
機能を追加することを想像してください。才能のある開発者として、あなたは毎日ますます多くの機能を追加しています。
テストを正常に機能させることはより困難になります。新しいテストごとにセットアップが複雑になり、テストスイートはより多くの時間を消費し始めます。これは、今やサポートする必要のある負担です。
これは一般的な問題であり、Reactコードベースで常に見られます。わずかな変更でも多くのテストが失敗するテストスイート。
1つの解決策は、テストスイートを分割することです。専用のテストを含む
BlogPage.test.js
新しいPostContent.test.js
ものを残して作成しますPostContent
。基本的な考え方は、に配置されるすべての関数はにあるPostContent
必要がありPostContent.test.js
、に配置されるすべての関数BlogPage
(URL解析など)はにある必要があるということですBlogPage.test.js
。
はい。
しかし、レンダリングするとどうなりますか
PostContent
副作用がありますか?
export const PostContent = ({ id }) => {
const [ text, setText ] = useState("")
useEffect(() => {
fetchPostContent(id)
}, [id])
const fetchPostContent = async () => {
const result = await fetch(`/post?id=${id}`)
if (result.ok) {
setText(await result.text())
}
}
return <p>{text}</p>
};
テストスイート
BlogPage.test.js
は、副作用を認識し、それらを処理する準備をする必要があります。たとえば、彼はfetch
答えを用意しておく必要があります。
テストスイートを分割して回避しようとした依存関係はまだ存在します。
私たちのテストの構成は確かに良くなりましたが、結局、私たちのテストの脆弱性を減らすことは何も起こりませんでした。
このためには、スタブ(またはモック)が必要
PostContent
です。
次のパートでは、これを行う方法を見ていきます。
本当に必要ですか?
ちなみに、エンドツーエンドテストからユニットテストへの移行について一言。
テストが2倍になることは、ユニットテストを作成していることを示す重要な指標です。
多くのベテランテスターは、コードベースが大きくなるにつれてテストの不安定性の問題が発生することを知っているため、ユニットテスト(およびモック)ですぐに新しいプロジェクトを開始します。
ユニットテストは通常、エンドツーエンドテストよりもはるかに小規模です。それらは非常に小さいため、多くの場合、3行または4行以下のコードしか必要としません。これにより、ペアリングやアンサンブルプログラミングなどのソーシャルコーディングプラクティスの優れた候補になります。
ユニットテストを行う場合でも、テストダブルは必ずしも必要ではありません。これらはスイート内のもう1つのツールであり、いつどのように適用するかを知る必要があります。
次のパートでは、基本的なモックテクニックについて説明します。