Martin FowlerのMocksはスタブではありません など、テストでのモッキングとスタブに関するさまざまな記事を読んだことがありますが、それでも違いはわかりません。
スタブ
最大の違いは、あなたがすでに書いたスタブがあらかじめ決められた振る舞いであるということです。そのため、テスト目的で偽造している依存関係(抽象クラスまたはインタフェース)を実装するクラスがあるとします。メソッドはsetレスポンスでスタブアウトされます。彼らは何も空想をしないでしょう、そしてあなたはすでにあなたのテストの外でそれのためにスタブコードを書いたでしょう。
モック
モックはあなたのテストの一部としてあなたがあなたの期待を持って設定しなければならないものです。モックはあらかじめ決められた方法で設定されていないので、テストにそれを実行するコードがあります。期待値を設定するコードは実行前に実行する必要があるため、ある意味でのモックは実行時に決定されます。
モックとスタブの違い
モックで書かれたテストは通常テストのためのinitialize -> set expectations -> exercise -> verify
パターンに従います。事前に書かれたスタブはinitialize -> exercise -> verify
に続きます。
モックとスタブの類似点
両方の目的は、クラスや関数のすべての依存関係のテストを排除して、テストがより焦点を絞っていること、およびそれらが証明しようとしていることをより簡単にすることです。
オブジェクトにはいくつかの定義がありますが、それらは現実的ではありません。一般用語はtest doubleです。この用語は、dummy、fake、stub、mockを含みます。
- Dummyオブジェクトは渡されますが、実際には使用されません。通常それらは単にパラメータリストを埋めるために使われます。
- Fakeオブジェクトは、実際には実用的な実装を持っていますが、通常は本番環境には適さないようなショートカットを取っています(インメモリデータベースがその良い例です)。
- Stubsは、テスト中に行われた呼び出しに対する定型の回答を提供します。通常、テスト用にプログラムされたもの以外のものにはまったく応答しません。スタブはまた、「送信した」メッセージ、あるいは「送信した」メッセージの数だけを記憶する電子メールゲートウェイスタブなど、通話に関する情報を記録することもできます。
- Mocksはここで話しているものです:彼らが受けると予想される呼び出しの仕様を形成する予想で予めプログラムされたオブジェクト。
モック対スタブ=行動テスト対国家テスト
テストごとに1つだけテストするの原則によると、1つのテストに複数のスタブが存在する可能性がありますが、通常はモックは1つだけです。
スタブを使用してライフサイクルをテストします。
モックでライフサイクルをテストする:
モックテストとスタブテストの両方が質問に答えを出します:結果は何ですか?
モックを使ったテストもまた興味を持っています:どのように結果は達成されましたか?
スタブは単純な偽物です。テストがスムーズに実行されるようにするだけです。
モックは賢いスタブです。あなたはあなたのテストがそれを通過することを確認します。
以下に、それぞれの説明と実際のサンプルを示します。
ダミー-API
を満たすための偽の値。
例:コンストラクターでを持たない多くの必須パラメーターを必要とするクラスのメソッドをテストする場合テストでeffectを使用すると、クラスの新しいインスタンスを作成する目的でダミーオブジェクトを作成できます。
Fake-外部インフラストラクチャに依存する可能性のあるクラスのテスト実装を作成します。 (単体テストではではなくが実際に外部インフラストラクチャと対話することをお勧めします。)
例:データベースにアクセスするための偽の実装を作成し、
in-memory
コレクションに置き換えます。
スタブ-メソッドをオーバーライドして、state-based
とも呼ばれるハードコードされた値を返します。
例:テストクラスはメソッド
Calculate()
に依存しており、完了までに5分かかります。 5分間待つのではなく、実際の実装をハードコードされた値を返すスタブに置き換えることができます。ほんの少しの時間しかかかりません。
モック-Stub
に非常に似ていますが、状態ベースではなくinteraction-based
です。これは、Mock
から何らかの値を返すことは期待しないが、メソッド呼び出しの特定の順序が行われると想定することを意味します。
例:ユーザー登録クラスをテストしています。
Save
を呼び出した後、SendConfirmationEmail
を呼び出す必要があります。
Stubs
とMocks
は、実際にはMock
のサブタイプです。どちらも実際の実装とテスト実装を入れ替えますが、具体的な理由は異なります。
codeschool.com コース、 Rails Testing for Zombies では、これらの用語の定義を示しています。
スタブ
指定された結果を返すコードでメソッドを置き換えるため。
モック
メソッドが呼び出されるというアサーションを持つスタブ。
Sean Copenhaverが彼の答えで述べたように、違いはモックが期待を設定するということです(すなわち、それらが呼ばれるかどうか、またはどのようにされるかについて主張をする)。
スタブはテストに失敗しません、モックはできます。
私はこの質問に関する最も簡単でわかりやすい答えが Roy Osherove 彼の本の中で与えられていると思います ユニットテストの技術 (85ページ)
スタブを扱っていることを伝える最も簡単な方法は、スタブがテストに失敗することは決してないということに気付くことです。テストが使用する主張は常にテスト中のクラスに対するものです。
一方、テストはモックオブジェクトを使用してテストが失敗したかどうかを検証します。 [...]
繰り返しますが、モックオブジェクトは、テストが失敗したかどうかを確認するために使用するオブジェクトです。
それはあなたが偽物に対して主張をしているならそれはあなたが偽物として偽物を使っていることを意味します。
上記の説明をすべて読んで、要約してみましょう。
モックは、単に特定のメソッドが呼び出されることを確認しながら、動作をテストしているだけです。スタブは特定のオブジェクトの(それ自体の)テスト可能なバージョンです。
あなたはアップルの方法をどういう意味ですか?
それらの間の最も重要な違いは彼らの意図です。
WHYスタブ vs. WHY mock で説明してみましょう。
私のMac Twitterクライアントのパブリックタイムラインコントローラ用のテストコードを書いているとしましょう。
これがテストサンプルコードです。
Twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
モックを書くことによって、あなたは期待が満たされていることを検証することによってオブジェクトのコラボレーション関係を発見しますが、スタブはオブジェクトの振る舞いをシミュレートするだけです。
もしあなたがモックについてもっと知りたいのなら、この記事を読むことをお勧めします: http://jmock.org/oopsla2004.pdf
それをデバッグと比較すると:
スタブ は、メソッドが正しい値を返すようにするためのものです。
モック は実際のようです - メソッドにステップインする そして正しい値を返す前に内部のすべてが正しいことを確認してください。
非常に明確で実用的であるために:
スタブ:偽造されるクラス/オブジェクトのメソッドを実装し、常に必要なものを返すクラスまたはオブジェクト。
JavaScriptでの例:
var Stub = {
method_a: function(param_a, param_b){
return 'This is an static result';
}
}
モック:スタブと同じですが、メソッドが呼び出されたときに「検証」するロジックが追加されているので、実装によってそのメソッドが呼び出されていることを確認できます。
例として@mLevanが言っているように、ユーザー登録クラスをテストしていると想像してください。 Saveを呼び出した後、SendConfirmationEmailを呼び出す必要があります。
非常に愚かなコード例:
var Mock = {
calls: {
method_a: 0
}
method_a: function(param_a, param_b){
this.method_a++;
console.log('Mock.method_a its been called!');
}
}
メンタルモデルを使う は、説明や記事のすべてではなく、これを理解するのに非常に役立ちました。
あなたの子供がテーブルの上にガラス板を持っていると想像してみてください、そして、彼はそれで遊び始めます。今、あなたはそれが壊れるのを恐れています。それで、あなたは彼に代わりにプラスチックプレートを与えます。それは Mock になるでしょう(同じ振る舞い、同じインターフェース、 "より柔らかい"実装)。
さて、あなたはプラスチックの代替品を持っていないと言うので、あなたはそれを説明します。それは スタブです 、あなたは事前に定義済みの状態を提供しました。
Dummy は彼が使ったことのないフォークになるでしょう...そして Spy はあなたがすでに使った同じ説明を提供するようなものになるでしょう。
Roy Osherove [ビデオリンク] によって出された説明が好きです。
作成されたすべてのクラスまたはオブジェクトは偽物です。あなたがそれに対する呼び出しを確認した場合それはモックです。それ以外の場合はスタブです。
fake は、スタブオブジェクトまたはモックオブジェクト(手書きまたはその他のもの)の両方を表すのに使用できる一般的な用語です。これらはどちらも実際のオブジェクトのように見えるためです。
偽物がスタブなのかモックなのかは、現在のテストでの使用方法によって異なります。インタラクションのチェックに使用されている(主張されている)場合、それはモックオブジェクトです。そうでなければ、それはスタブです。
Fakes テストがスムーズに実行されるようにします。それはあなたの将来のテストの読者がそのソースコードを読む必要なしに(外部リソースに依存する必要なしに)、偽のオブジェクトの振る舞いがどうなるかを理解することを意味します。
テスト実行が円滑に行われるとはどういう意味ですか?
たとえば、次のコードを見てください。
public void Analyze(string filename)
{
if(filename.Length<8)
{
try
{
errorService.LogError("long file entered named:" + filename);
}
catch (Exception e)
{
mailService.SendEMail("[email protected]", "ErrorOnWebService", "someerror");
}
}
}
mailService.SendEMail() methodをテストして、テストメソッドでExceptionをシミュレートする必要があるので、その結果をシミュレートするためにFake StubのerrorServiceクラスを作成してからテストを実行するだけです。コードはmailService.SendEMail()メソッドをテストできます。ご覧のとおり、他のExternal Dependency ErrorServiceクラスからの結果をシミュレートする必要があります。
テストダブルスを見てみましょう:
Stub :Stubは事前定義データを保持し、テスト中にそれを使用して呼び出しに応答するオブジェクトです。のように:メソッド呼び出しに応答するためにデータベースからデータを取得する必要があるオブジェクト。
モック :モックは受信した呼び出しを登録するオブジェクトです。テストアサーションでは、期待されるすべてのアクションが実行されたことをMocksで確認できます。のように:Eメール送信サービスを呼び出す機能。もっとチェックするには これ をチェックしてください。
JMockの開発者による論文 モックロール、オブジェクトではない
スタブは、既定の結果を返す運用コードのダミー実装です。モックオブジェクトはスタブとして機能しますが、ターゲットオブジェクトとその隣接オブジェクトとの相互作用を計測するためのアサーションも含みます。
そのため、主な違いは以下のとおりです。
まとめると、 Fowler's article title:からの混乱を分散させようともしています: モックはスタブですが、スタブ だけではありません。
私はUncleBob The Little Mocker によってこの興味深い記事に出会いました。理解しやすいようにすべての用語を説明しているので、初心者には便利です。 Martin Fowlersの記事は、特に私のような初心者のための読み物です。
下記のC#とMoqフレームワークを使ったモックとスタブの例を見てください。 Moqにはスタブ用の特別なキーワードはありませんが、スタブを作成するためにMockオブジェクトを使用することもできます。
namespace UnitTestProject2
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class UnitTest1
{
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method calls Repository GetName method "once" when Id is greater than Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Once);
}
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method doesn't call Repository GetName method when Id is Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(0);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Never);
}
/// <summary>
/// Test using Stub to Verify that GetNameWithPrefix method returns Name with a Prefix
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
{
// Arrange
var stubEntityRepository = new Mock<IEntityRepository>();
stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
.Returns("Stub");
const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
var entity = new EntityClass(stubEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
}
}
public class EntityClass
{
private IEntityRepository _entityRepository;
public EntityClass(IEntityRepository entityRepository)
{
this._entityRepository = entityRepository;
}
public string Name { get; set; }
public string GetNameWithPrefix(int id)
{
string name = string.Empty;
if (id > 0)
{
name = this._entityRepository.GetName(id);
}
return "Mr. " + name;
}
}
public interface IEntityRepository
{
string GetName(int id);
}
public class EntityRepository:IEntityRepository
{
public string GetName(int id)
{
// Code to connect to DB and get name based on Id
return "NameFromDb";
}
}
}
スタブとモックのテストの観点
スタブ はスタティックで スタティック 方法でユーザーによって行われたダミーの実装です。つまり、実装コードを記述します。それでそれはサービス定義と動的条件を扱うことができません、通常これはモックフレームワークを使わずにJUnitフレームワークでされます。
Mock もダミーの実装ですが、その実装は 動的 MockitoのようなMockingフレームワークを使用することによって行われます。そのため、条件とサービスの定義を動的な方法で処理できます。つまり、実行時にコードからモックを動的に作成できます。 それで、モックを使ってスタブを動的に実装することができます。
スタブ テストを実行するのに役立ちます。どうやって?テストを実行するのに役立つ値を与えます。これらの値自体は実際のものではなく、テストを実行するためだけにこれらの値を作成しました。例えば、データベーステーブルの値に似た値を与えるためにHashMapを作成します。データベースと直接対話する代わりに、Hashmapと対話します。
モック はテストを実行する偽のオブジェクトです。我々が主張するところ。
スタブは、テスト中に未処理の例外を回避するために使用される空の関数です。
function foo(){}
モックは、テスト中にOS、環境、またはハードウェアの依存関係を回避するために使用される人工的な機能です。
function foo(bar){ window = this; return window.toString(bar); }
アサーションと状態に関して:
参考文献
たくさんの有効な答えがありますが、このフォームのおじさんに言及する価値があると思います。 https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html
例でこれまでで最高の説明!
私は私の答えにpythonの例を使って違いを説明しました。
スタブ - スタブは、開発ライフサイクルの早い段階でクラスのメソッドを実装するために使用されるソフトウェア開発手法です。それらは、既知のインタフェースの実装のプレースホルダとして一般的に使用されています。ここでは、インタフェースは確定または既知ですが、実装はまだ確定または確定していません。スタブから始めます。つまり、単に関数の定義を書き留めて、後で実際のコードを残すということです。利点は、メソッドを忘れずに済み、コードでそれを見ながら自分のデザインについて考え続けることができるということです。スタブに静的応答を返させて、その応答をコードの他の部分ですぐに使用できるようにすることもできます。スタブオブジェクトは有効な応答を提供しますが、どの入力を渡しても静的です。常に同じ応答が返されます。
class Foo(object):
def bar1(self):
pass
def bar2(self):
#or ...
raise NotImplementedError
def bar3(self):
#or return dummy data
return "Dummy Data"
モック オブジェクトはモックテストケースで使用され、特定のメソッドがそれらのオブジェクトに対して呼び出されることを検証します。モックオブジェクトは、実際のオブジェクトの動作を制御された方法で模倣したシミュレートオブジェクトです。通常、他のオブジェクトの動作をテストするためにモックオブジェクトを作成します。モックを使用すると、単体テストには利用できない、または処理が面倒なリソースをシミュレートできます。
mymodule.py:
import os
import os.path
def rm(filename):
if os.path.isfile(filename):
os.remove(filename)
test.py:
from mymodule import rm
import mock
import unittest
class RmTestCase(unittest.TestCase):
@mock.patch('mymodule.os')
def test_rm(self, mock_os):
rm("any path")
# test that rm called os.remove with the right parameters
mock_os.remove.assert_called_with("any path")
if __== '__main__':
unittest.main()
これは非常に基本的な例で、rmを実行して、呼び出されたパラメータをアサートします。ここに示すように、関数だけでなくオブジェクトでモックを使用することもできます。また、テストのためにスタブを置き換えるためにモックオブジェクトを使用できるように、値を返すこともできます。
unittest.mock の詳細、python 2.x mockでの注意はunittestには含まれていませんが、pip(pip install mock)でダウンロードできるダウンロード可能なモジュールです。
Roy Osheroveによる「The Art of Unit Testing」も読んだことがありますが、PythonとPythonの例を使用して同様の本を書いていれば素晴らしいと思います。誰かがそのような本を知っているならば、共有してください。乾杯:)
スタブはテスト目的で作成された偽のオブジェクトです。モックは、予想される呼び出しが事実上発生したかどうかを記録するスタブです。
スタブ はコンポーネントのインタフェースを実装するオブジェクトですが、呼び出されたときにコンポーネントが返すものを返す代わりに、スタブはテストに適した値を返すように設定できます。スタブを使用すると、ユニットテストはユニットがその共同作業者からのさまざまな戻り値を処理できるかどうかをテストできます。ユニットテストで実際の共同作業者の代わりにスタブを使用することは、次のように表現できます。
単体テスト - >スタブ
ユニットテスト - >ユニット - >スタブ
ユニットテストはユニットの結果と状態をアサートします
まず単体テストでスタブを作成し、その戻り値を設定します。それからユニットテストはユニットを作成し、その上にスタブを設定します。今度は単体テストが次にスタブを呼び出すユニットを呼び出します。最後に、単体テストで、そのユニットに対するメソッド呼び出しの結果についてアサーションが行われます。
Mock はスタブに似ていますが、Mockで呼び出されたメソッドを判別できるようにするメソッドもあります だけです。したがって、モックを使用して、ユニットがさまざまな戻り値を正しく処理できるかどうかと、ユニットがコラボレータを正しく使用しているかどうかをテストすることができます。たとえば、daoオブジェクトから返された値から、データがStatementまたはPreparedStatementのどちらを使用してデータベースから読み取られたのかを確認することはできません。また、値を返す前にconnection.close()メソッドが呼び出されたかどうかもわかりません。これはモックで可能です。言い換えれば、モックは共同作業者とのユニットの完全な相互作用をテストすることを可能にします。ユニットによって使用される値を返すコラボレータメソッドだけではありません。単体テストでモックを使用すると、次のように表現できます。
ユニットテスト - >モック
ユニットテスト - >ユニット - >モック
ユニットテストはユニットの結果と状態についてアサートします
単体テストは、モックで呼び出されたメソッドでアサートします
もっと詳しく>> ここ
スタブは、テストで設定した期待戻り値を持つメソッドで使用されます。モックは、それらが呼び出されることをアサートで検証されるvoidメソッドで使用されます。
被験者は、特定のプロンプト(関数呼び出し)または他の刺激に応答して行動を実行します。これがテスト状況の具体例です。
ある学生が緊急医療技術者になることを学びました。このテストの状況に慣れていない場合は、Ian Gallagherの Shameless シーズン6、エピソード10を参照してください。
テスト目的でさまざまな病気の患者を見つけるのは高すぎます。代わりにアクターを使います。私たちは被験者(イアン)に、「あなたは現場に到着し、患者は動けなくなり、意識不明になります。あなたが最初に何をしますか?」と尋ねます。イアンは「現場が安全かどうかを確認します」と答えた。そしてテストインストラクターは「現場は安全だ」と言います。
講師(および俳優)は、被験者の質問に対して任意の回答を挿入することができます。
ここでは、インストラクター(そしてアクター)はモックです。 医療訓練は、コンピュータ科学者と同じようにこの用語を使用します(例:モックコードシミュレーション)。
あなたはYahoo、あなたが聞いたことのある新しいEメールサービスをテストしている。登録するには、誕生日と他の煩わしい質問への回答を提供する必要があります。
ウェブサイトはあなたが21歳以上であることを必要とします。そのため、1970年1月1日という値を入力します。これは要件を満たしており、誕生日を覚えて入力するワークフローを実装するという面倒なプロセスからあなたを救います。
この日付はスタブです。 このWordの用法は、コンピュータサイエンスに固有のものです。
モック - モックは、メソッドや関数(あるいはモッククラスの場合のように、一群のメソッドや関数)への呼び出しを阻止します。それはその方法や機能に代わるものではありません。その傍受では、モックは入出力の記録、呼び出しの短絡、戻り値の変更など、必要なことは何でも実行できます。
スタブ - スタブとは、メソッドまたは関数のスタブと同じインターフェイス/シグネチャを持つ、メソッドまたは関数(またはスタブクラスの場合のようなメソッドおよび関数のグループ)の有効で完全に機能する実装です。それがスタブになっているメソッドと機能。スタブ化された実装は一般的に単体テストのコンテキスト内で許容できることだけを行います。つまり、スタブしているものの動作を模倣しながらIOは実行されません。
私は「単体テストの技術」を読んでいて、次の定義につまずきました。
fakeは、スタブまたはモックオブジェクト(手書きまたはその他)を記述するために使用できる一般的な用語です。どちらも実際のオブジェクトのように見えるためです。フェイクがスタブかモックかは、現在のテストでどのように使用されているかによります。インタラクションのチェックに使用される(アサートされる)場合、それは模擬オブジェクトです。それ以外の場合、それはstubです。
テストしたいEmployeeServiceというクラスがあり、そのクラスにEmployeeDaoという名前のインタフェースへの依存関係が1つあるとします。
public class EmployeeService{
private EmployeeDao dao;
public EmployeeService(Dao dao){this.dao = dao;}
public String getEmployeeName(int id){
Employee emp = bar.goToDatabaseAndBringTheEmployeeWithId(id);
return emp != null?emp.getFullName:null;
}
//Further state and behavior
}
public interface EmployeeDao{
Employee goToDatabaseAndBringTheEmployeeWithId(int id);
}
テストクラスの中:
public class EmployeeServiceTest{
EmployeeService service;
EmployeeDao mockDao = Mockito.mock(EmployeeDao.class);//Line 3
@Before
public void setUp(){
service = new EmployeeService(mockDao);
}
//Tests
//....
}
3行目の上記のテストクラスでは、モッキングフレームワーク(この場合はMockito)に、「Hey、Mockito、EmployeeDao機能を持つオブジェクトを作成してください」と述べています。フレームワークは、メソッドgoToDatabaseAndBringTheEmployeeWithId
を持つが実際にはボディを持たないオブジェクトを作成しようとしています。そのモックに何をすべきか指示するのはあなたの仕事です。これはモックです。
しかし、EmployeeDaoインターフェースを実装するクラスを作成し、代わりにそれをテストクラスで使用することもできます。
public EmployeeDaoStub implements EmployeeDao{
public Employee goToDatabaseAndBringTheEmployeeWithId(int id){
//No trip to DB, just returning a dummy Employee object
return new Employee("John","Woo","123 Lincoln str");
}
}
今回はテストクラスの内部でモックの代わりにスタブを使用します。
public class EmployeeServiceTest{
EmployeeService service;
EmployeeDao daoStub = new EmployeeDaoStub();//Line 3
@Before
public void setUp(){
service = new EmployeeService(daoStub);
}
//Tests
//....
}
つまり、すべてをまとめると、スタブは、目的の状態にするためだけに依存関係を模倣するために作成した(または他のユーザーが作成した)クラスです。はい、他のすべての人が述べているように、それはモックが一般的にモッキングフレームワークによって作成されているのに対し、ほとんどその状態についてです。しかし、スタブを使えば、どのクラスを取得しようとしているかがわかります。それが、作成したクラスです。
ところで、依存関係がインタフェースではなくクラスである場合は、そのクラスを拡張してスタブを作成できます。
スタブとモックはどちらも外部の依存関係をオーバーライドしますが、違いは
スタブ - > データをテストするには
モック - > 動作をテストする
偽/ダミー - > 何もテストしない (テスト中にロギングノイズを避けるためにLogger
を置き換えてください)
以下は私の理解です...
テストオブジェクトをローカルに作成し、それにローカルサービスを提供する場合は、モックオブジェクトを使用しています。これはあなたがあなたのローカルサービスに実装したメソッドのテストをするでしょう。振る舞いを検証するために使用されます
実際のサービスプロバイダからテストデータを取得するときは、テストバージョンのinterfaceからオブジェクトのテストバージョンを取得すると、スタブを使用しているため、スタブは特定の入力を受け付けて実行に役立つ対応する出力を提供できます状態確認...
モックは、両方とも技術的および機能的オブジェクトです。
モックは技術的です。 byte code generationのおかげで、実際にはモックライブラリ(EasyMock、JMockit、および最近ではMockitoがこれらで知られています)によって作成されます。
モックの実装はgenerated可能な方法ですinstrumentメソッドが呼び出されたときに特定の値を返すだけでなく、検証などのその他のこともモックメソッドが特定のパラメーター(厳密なチェック)またはパラメーター(厳密なチェックなし)で呼び出されたこと。
モックのインスタンス化:
@Mock Foo fooMock
動作の記録:
when(fooMock.hello()).thenReturn("hello you!");
呼び出しの検証:
verify(fooMock).hello()
これらは、明らかにFooクラス/動作をインスタンス化/オーバーライドする自然な方法ではありません。それが私が技術的な側面に言及する理由です。
しかしモックも機能的は、SUTから隔離する必要があるクラスのインスタンスであるためです。記録された動作を使用して、SUTでスタブを使用する場合と同じ方法で使用できます。
スタブは単なる機能オブジェクトです。これは、SUTから分離する必要があるクラスのインスタンスであり、それがすべてです。つまり、ユニットテスト中に必要なスタブクラスとすべての動作フィクスチャの両方を明示的に定義する必要があります。
たとえば、hello()
をスタブするには、Foo
クラスをサブクラス化する(または、そのインターフェイスを実装して)hello()
をオーバーライドする必要があります。
public class HelloStub extends Hello{
public String hello {
return "hello you!";
}
}
別のテストシナリオで別の値を返す必要がある場合、おそらく戻り値を設定する一般的な方法を定義する必要があります。
public class HelloStub extends Hello{
public HelloStub(String helloReturn){
this.helloReturn = helloReturn;
}
public String hello {
return helloReturn;
}
}
その他のシナリオ:副作用メソッド(リターンなし)があり、そのメソッドが呼び出されたことを確認する場合、おそらくメソッドが呼び出された回数をカウントするためにスタブクラスにブール値またはカウンターを追加する必要がありました。
結論
スタブは、多くの場合、ユニットテスト用に書き込むために多くのオーバーヘッド/コードを必要とします。箱から出して記録/検証機能を提供することにより、モックが妨げているもの。
そのため、最近では、優れたモックライブラリの出現により、スタブアプローチが実際に使用されることはほとんどありません。
Martin Fowlerの記事について:モックを使用し、スタブを避けている間、私は「モック主義者」プログラマーだとは思わない。
しかし、本当に必要なとき(依存関係を悩ます)にモックを使用し、モックがオーバーヘッドになるような依存関係を持つクラスをテストするときは、テストスライシングおよびミニ統合テストを好みます。