モッキングとは何ですか?


回答:


598

プロローグ:名詞のモックを辞書で検索すると、単語の定義の1つが模倣として作成されたものであることがわかります。


モッキングは主に単体テストで使用されます。テスト中のオブジェクトは、他の(複雑な)オブジェクトに依存している場合があります。オブジェクトの動作を分離するには、他のオブジェクトを、実際のオブジェクトの動作をシミュレートするモックに置き換えます。これは、実際のオブジェクトを単体テストに組み込むことが実用的でない場合に役立ちます。

つまり、モッキングとは、実際のオブジェクトの動作をシミュレートするオブジェクトを作成することです。


時にはあなたは区別することができますモックとは対照的に、スタブ。この件については意見の相違があるかもしれませんが、私のスタブの定義は「最小限の」シミュレーションオブジェクトです。スタブは、テスト対象のオブジェクトがテストを実行できるようにするだけの十分な動作を実装します。

モックはスタブのようなものですが、テストでは、テスト対象のオブジェクトが期待どおりにモックを呼び出すことも確認します。テストの一部は、モックが正しく使用されたことを確認することです。

例を挙げましょう:レコードを格納するための単純なメモリ内構造を実装することにより、データベースをスタブできます。次に、テスト対象のオブジェクトは、データベーススタブに対してレコードを読み書きして、テストを実行できるようにします。これにより、データベースに関連しないオブジェクトの動作をテストできます。テストを実行するためだけにデータベーススタブが含まれます。

代わりに、テスト対象のオブジェクトが特定のデータをデータベースに書き込むことを確認する場合は、データベースをモックする必要があります。次に、データベースモックに何が書き込まれたかに関するアサーションをテストに組み込みます。


18
これは良い答えですが、モックの概念をオブジェクトに不必要に制限します。「オブジェクト」を「ユニット」に置き換えると、より一般的になります。
ホジェリオ

1
スタブとモックの違いは理解しています。唯一のことは、スタブを使用してケースをテストし、それが成功した場合、すでにスタブを使用していると結論付けられないため、検証が不要になったということです。
Honey

91

他の答えは、あざけるとは何かを説明しています。さまざまな例を挙げて説明します。そして、私を信じて、それは実際にはあなたが考えるよりもはるかに簡単です。

tl; dr元のクラスのインスタンスです。他のデータが注入されているので、注入された部分のテストを回避し、クラス/関数の実装の詳細のテストのみに集中できます。

簡単な例:

class Foo {
    func add (num1: Int, num2: Int) -> Int { // Line A 
        return num1 + num2 // Line B
    }
}

let unit = Foo() // unit under test
assertEqual(unit.add(1,5),6)

ご覧のとおり、私はLineAをテストしていません。つまり、入力パラメーターを検証していません。num1、num2がIntegerかどうかを確認するための検証は行っていません。私はそれに反対することはありません。

LineB(私の実装)がモックされた値1を与え、5期待どおりに動作しているかどうかを確認するためだけにテストしています。

明らかに、実際の言葉では、これははるかに複雑になる可能性があります。パラメータは、Person、Addressなどのカスタムオブジェクトにすることも、実装の詳細を複数にすることもできます+。しかし、テストのロジックは同じです。

非コーディングの例:

空港のセキュリティのために電子機器のタイプとブランド名を識別するマシンを構築していると仮定します。マシンは、カメラで見たものを処理することでこれを行います。

次に、マネージャーがドアを通り、ユニットテストを行うように依頼します。

次に、開発者として、MacBook pro、Google Nexus、バナナ、iPadなどの実際のオブジェクトを1000個前に持ってきて、テストしてすべてが機能するかどうかを確認します。

しかし、同じ外観のMacBook pro(実際の内部部品はありません)またはその前にあるプラスチックバナナのような、模造オブジェクトを使用することもできます。1000の本物のラップトップや腐ったバナナへの投資から身を守ることができます。

ポイントは、バナナが偽物であるかどうかをテストしようとしているのではないということです。ラップトップが偽物であるかどうかもテストしません。あなたがやっているすべては、それが言うバナナを見たら、あなたのマシンならばテストしているnot an electronic deviceとMacBookのために、それは言うプロ:Laptop, Apple。マシンにとって、その検出の結果は、偽/偽の電子機器と実際の電子機器で同じになるはずです

上記のロジックは、実際のコードの単体テストにも適用されます。つまり、関数は、実際の入力(および相互作用)から取得した、またはモックした実際の値と同じように機能するはずです。単体テスト中に注入する値。そして、実際のバナナやMacBookを使用しないようにする方法と同じように、ユニットテスト(およびモック)を使用すると、サーバーが500、403、200などのステータスコードを返すような処理を行う必要がなくなります(強制的にサーバーが500をトリガーするのは、サーバーがダウンしているときのみですが、200はサーバーがアップしているときです。サーバーのアップとダウンを切り替える間、常に10秒間待機する必要がある場合、100に焦点を当てたテストを実行するのは困難です。したがって、代わりに、ステータスコード500、200、403などの応答を挿入/模擬し、ユニット/関数を挿入/模擬値でテストします。

コーディング例:

iOSアプリケーションを作成していて、ネットワーク呼び出しがあるとします。あなたの仕事はアプリケーションをテストすることです。ネットワークコールが期待どおりに機能するかどうかをテスト/識別することは、お客様の責任ではありません。これをテストするのは、他の当事者(サーバーチーム)の責任です。この(ネットワーク)依存関係を削除しそれを回避するすべてのコードを引き続きテストする必要があります。

ネットワークコールは、JSON応答でさまざまなステータスコード404、500、200、303などを返すことができます。

アプリはそれらすべてで機能すると想定しています(エラーの場合、アプリは予想されるエラーをスローする必要があります)。モックを使用して行うのは、「実際のネットワーク応答に似た架空の」ネットワーク応答(JSONファイルを含む200コードなど)を作成し、「実際のネットワーク呼び出しを行ってネットワーク応答を待つ」ことなくコードテストすることです。すべての種類のネットワーク応答のネットワーク応答を手動でハードコード/返送し、アプリが期待どおりに機能しているかどうかを確認します。(あなたは決してそれはあなたの責任ではないため、不正なデータと200をテスト/負いません、あなたの責任でテストすることで、あなたの正しい200でアプリを、または400、500、あなたのテストの場合、あなたのアプリケーションは、右のエラーをスローした場合)

これは架空のものと同様に、架空のものを作成します。

これを行うために、元のコードを使用することはできません(元のコードには事前に応答が挿入されていませんよね?)。あなたそれに何かを追加する必要があります。通常は必要とされないダミーのデータ(またはクラスの一部)を挿入/挿入します。

したがって、元のクラスのインスタンスを作成し、必要なもの(ここではネットワークHTTPResponse、データ、または失敗した場合は、正しいerrorString、HTTPResponseを渡します)を追加して、モックされたクラスをテストます。

一言で言えば、モックとは、テスト対象を単純化して制限し、クラスが依存するものにフィードを提供することです。この例では、ネットワーク呼び出し自体のテスト回避、代わりに、注入された出力/応答でアプリが期待どおりに機能するかどうかをテストします- クラスをモックすることによって

言うまでもなく、各ネットワーク応答を個別にテストします。


今私がいつも頭に浮かんだ質問は、契約/エンドポイント、そして基本的に私のAPIのJSON応答は常に更新されるということでした。これを考慮した単体テストを作成するにはどうすればよいですか?

これについて詳しく説明するには、モデルにという名前のキー/フィールドが必要だとしますusername。これをテストすると、テストに合格します。2週間後、バックエンドはキーの名前をに変更しますid。テストはまだ成功しています。正しい?か否か?

モックを更新するのはバックエンド開発者の責任ですか?彼らが最新のモックを提供することは私たちの合意の一部であるべきですか?

上記の問題に対する答えは次のとおりです。ユニットテスト+クライアント側の開発者としての開発プロセスは、古いモック応答をキャッチする必要があります。どのように私に尋ねたら?よく答えは:

実際のアプリは、更新されたAPIを使用せずに失敗します(または失敗せず、目的の動作をしません)。したがって、失敗した場合は、開発コードに変更を加えます。これもまた、テストの失敗につながります。...これを修正する必要があります。(実際にTDDプロセスを正しく行う場合は、テストを記述しない限りフィールドに関するコードを記述しないようにします。テストが失敗し、実際の開発コードを記述してください。)

つまり、バックエンドで「モックを更新しました」と言う必要はありません。最終的には、コードの開発/デバッグによって発生します。itそれはすべて開発プロセスの一部であるためです!バックエンドが偽の応答を提供する場合、それは簡単です。

これに関する私の全体的な要点は、(更新されたモックAPI応答の取得を自動化できない場合)人間による操作が必要です。つまり、JSONを手動で更新し、値が最新であることを確認するための短い会議を行うことがプロセスの一部になります。

このセクションは、CocoaHeadミートアップグループでの緩やかな議論のおかげで書かれました。


iOS開発者のみ:

モックの非常に良い例は、Natasha Muraschevによるこの実践的なプロトコル指向の講演です。スライドを実際のビデオと同期しなくなる可能性がありますが、18:30までスキップしてください。

筆記録のこの部分が本当に好きです:

これはテスト中であるため... getからの関数Gettableが呼び出されることを確認したいのです。これは、関数が返され、関数が理論的にどこからでも食品の配列を割り当てることができるためです。それが呼び出されることを確認する必要があります。


3
素晴らしい例です。この特定の例では、サブクラスがモックとして機能することを追加しますが、この例でもスタブを使用しています。ハードコードされたJSON応答は、スタブ化された応答と見なされます。モックとスタブを区別するのは難しいため、これを追加するだけですが、この例では、両方を一緒に使用する方法を明確に示しています。
user3344977 2017

素晴らしい説明、ありがとうございます。APIの変更に関する質問に対する1つの小さな調整。それがAPIではないので、開発プロセスに参加していない場合はどうなりますか?クライアントライブラリがいつ失敗するか知りたい。
ThinkDigital

@ThinkDigital優れたAPIプロバイダーには適切なリリースノートがあり、変更を適切に伝達します。そのチャネルがない場合は、会議に参加して議論するときかもしれません。優れた開発者は常に新しいバージョンのAPIの変更を調査し、APIバージョンのアップグレードだけを避けます。APIバージョンはありますか?それらのどちらもそれをキャッチしない場合は、QAingで確認できます。次に、テストを更新します←チーム全体の義務。→単一の開発者に義務を課す:あまり気にしないでください。サーバーがエラーを返す場合、またはサーバーがエラーを返さないがjsonを解析できない場合、または正しいケースを処理する場合のみを処理します。
Honey

返信いただきありがとうございます、@ Honey!私の場合、APIを備えたpub.devのクライアントを維持していますが、それは非常に不足しています。そのため、公式のAPIを使用するよりも、サイトをスクレイピングしてAPIを作成する方が適切でした。このため、サイトに変更を加えるとコードが壊れる可能性があり、この場合は誰も更新する必要はありません。このサイトはオープンソースですが、より些細な基準で行われた変更に基づいたAPIを維持することは別のことです。
ThinkDigital

32

SOに関するたくさんの回答と、モックに関するWeb上の良い投稿があります。あなたが探し始めるとよいかもしれない場所の1つは、Martin Fowler Mocks Aren's Stubsによる投稿です。彼は、モッキングの多くのアイデアについて議論しています。

1つの段落で-モッキングは、依存関係に依存せずにコードのユニットのテストを可能にする特定のテクニックの1つです。一般に、モックを他のメソッドと区別するのは、コードの依存関係を置き換えるために使用されるモックオブジェクトによって期待値を設定できることです。モックオブジェクトは、コードによってどのように呼び出され、どのように応答するかを認識します。


あなたの元の質問はTypeMockについて言及していたので、以下にその答えを残しておきます。

TypeMockは、商用モックフレームワークの名前です。

RhinoMocksやMoqのような無料のモックフレームワークのすべての機能に加えて、いくつかのより強力なオプションを提供します。

TypeMockが必要かどうかは非常に議論の余地があります。無料のモッキングライブラリを使用すると、たいていのモックを作成できます。多くの人は、TypeMockが提供する機能によって、カプセル化された設計から離れることが多いと主張しています。

別の答えが述べたように、「TypeMocking」は実際には定義された概念ではありませんが、TypeMockが提供するモッキングのタイプを意味し、CLRプロファイラーを使用して実行時に.Net呼び出しをインターセプトし、オブジェクトを偽造するはるかに優れた機能を提供します(要件ではありません)インターフェースや仮想メソッドが必要など)。


@MasoudはTypeMockについて言及していません。彼の質問は、一般に「タイプのモック」についてでした。
Peter Lillevold、2010

4
@ピーター-別のコメントが言ったように、質問の編集履歴を確認してください。回答を投稿した後、元の質問が完全に変更されても、できることは多くありません。
デビッドホール

9

モックは、実際のメソッド/オブジェクトの動作を制御された方法でシミュレートするメソッド/オブジェクトです。模擬オブジェクトは単体テストで使用されます。

多くの場合、テスト中のメソッドは、その中の他の外部サービスまたはメソッドを呼び出します。これらは依存関係と呼ばれます。モックされると、依存関係は定義したとおりに動作します。

依存関係はモックによって制御されているので、コーディングしたメソッドの動作を簡単にテストできます。これは単体テストです。

モックオブジェクトの目的は何ですか?

モック対スタブ

単体テストと機能テスト


7

モッキングは、テストのために実際のオブジェクトの動作をシミュレートする疑似オブジェクトを生成しています


5

タイプをモックする目的は、テストを特定のユニットに分離するために依存関係を切断することです。スタブは単純なサロゲートですが、モックは使用を確認できるサロゲートです。モックフレームワークは、スタブとモックの生成に役立つツールです。

編集:元の文言が「タイプのモック」に言及して以来、これはTypeMockに関連しているという印象を受けました。私の経験では、一般的な用語は単に「あざける」です。TypeMockに関する以下の情報は無視してください。

TypeMock Isolatorは、ILをオンザフライで変更できるという点で、他のほとんどのモックフレームワークとは異なります。これにより、他のほとんどのフレームワークでは模倣できないタイプやインスタンスを模擬できます。これらのタイプ/インスタンスを他のフレームワークと模擬するには、独自の抽象化を提供し、これらを模擬する必要があります。

TypeMockは、クリーンなランタイム環境を犠牲にして優れた柔軟性を提供します。TypeMockがその結果を達成する方法の副作用として、TypeMockを使用すると非常に奇妙な結果が得られることがあります。


@MasoudはTypeMockについて言及していません。彼の質問は、一般に「タイプのモック」についてでした。
Peter Lillevold、2010

1
@ピーター:元の表現は「タイプのモックとは何ですか?」でした。
Brian Rasmussen、

知っている。「type mocking」は「TypeMock」と同等ではないので、あなたと@Odedの両方の答えはかなりずれています。
Peter Lillevold、2010

1
@ピーター:私の経験では、一般的な用語は「あざける」ですが、いずれにせよ、うまくいけばそれを明確にするために私の回答を更新しました。入力いただきありがとうございます。
Brian Rasmussen、

3

TypeMockアイソレーターモックフレームワークの使用はTypeMockingだと思います。

これは、ユニットテストで使用するモックを生成するツールであり、IoCを考慮してコードを記述する必要はありません。


@MasoudはTypeMockについて言及していません。彼の質問は、一般に「タイプのモック」についてでした。
Peter Lillevold、2010

3
実際、元の質問には「モッキング」の前に「タイプ」という単語が含まれていましたが、後で編集されました。そのため、回答の一部にはTypeMockに関する特定の情報が含まれています。
マーティンリバセージ2010

1

モックにネットワークリクエストが含まれている場合、別の方法として、実際のテストサーバーにアクセスする方法があります。このサービスを使用して、テストの要求と応答を生成できます。http://testerurl.com/


アクセスしようとしたところ、数分かかりました。秘密裏にリクエストをログに記録していないと誰が言っているのですか?最後に、これはコメントとしてより良いかもしれません:)
キーレン・ジョンストーン

無料のホスティングに移行したくなかったので、実際に削除しました。はい、これはコメントであるべきでした。オープンソースなので、リクエストのロギングについて懸念がある場合は、独自に実行できます。github.com/captainchung/TesterUrl
マシューチョン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.