モックは噛まない!React TestingLibraryでモッキングをマスターする

記事の翻訳は、コース「JavaScriptでの自動化のテスト」の開始を見越して作成されました










モック-噛まないでください!



これらは、より単純で信頼性の高いテストを作成できるように設計されています。このシリーズの記事では、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モックはあなたのテストが速くて壊れにくいこと保証すると言います



これは本当ですが、これは私がモックを使用する主な理由ではありません。

モックを使用するのは、テストを互いに独立させるのに役立つからです。



これが当てはまる理由を理解するために、例を見てみましょう。



なぜモキ?



以下は、BlogPage2つのことを実行するコンポーネントのリストです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つのツールであり、いつどのように適用するかを知る必要があります。



次のパートでは、基本的なモックテクニックについて説明します。






All Articles