2009-03-04 11 views

答えて

1

モックは、特定の方法で動作するように指示できる代理です。これは、モックオブジェクトで実際のインスタンスを切り替えることによって、依存関係を取り除きたい場所をテストするのに便利です。

スタブモックとは異なり、実際の使用状況を把握しているので、モックが期待通りに使用されたかどうかをテストで確認できます。

詳細情報Fowlerの記事here

9

したがって、あなたは他の何かに依存するクラスを持っています。

車にはエンジンが必要です。

車はエンジンに依存しています。車とエンジンが一緒に動作することをテストするのは簡単ですが、エンジンなしで車をテストすること、または車がエンジンを正しく呼び出すことはどうですか? 私たちができることは、エンジンの代わりに何か(偽物)を置き、ガスを押して(電話をかける)、擬似(モック)エンジンがスロットルボディに正しい入力を受け取ったことを確認することです。システム全体を検証するのではなく、モックオブジェクトを使って測定することで、孤立した状態でテストするだけです。

それはあなたがあなたのクラスのためのユニットテストを記述する場合、いくつかの点で、あなたのテストは、外部を呼び出すコードを実行し、状況に遭遇するだろう

3

を実際に方法より複雑で道より強力な取得しますが、...リソース。ほとんどの場合、これはデータベースですが、他のものも可能です。そのような状況では、テストを実行するたびに実際にサービスを呼びたくないので、私は通常、クレジットカードの請求サービスプロバイダを例として使用します。

このような状況では、サービスオブジェクトを、リソースを使用しない一種の偽のサービスに置き換えることが一般的です。これは、スタブまたはモックオブジェクトと呼ばれます。スタブとモックの違いはいくつかの議論の対象と思われますが、本質的には同じです。

Rhino MockのようなMockingフレームワークは、実際のサービスと同じように応答する模擬オブジェクトを作成するのに役立ちます。テストを実行するたびに再生できるサービスコールの実際の応答の記録を比較することができます。

2

本当に理解するには、あなたが最初の4つの概念の相互作用が

は何偽物

は何(サイのモックのような)分離フレームワーク

何ですかをテストして何

を把握する必要がモックスタブ

最後にモックとは何か

相互作用テストは、特定のメソッド(テストしているメソッド)が、別のクラスの別のメソッド(外部依存関係)を使用するパラメータで呼び出すかどうかを調べることです。 無効なパラメータで呼び出されるたびにログを記録するクラスがあるとします。スタブとの違いを明確にし、あざけりのために、私は2つの外部依存関係(IStringAnalyzerとILooger)を追加しました:

テストしたい。この例では
class SomeClass 
{ 
    IStringAnalyzer stringAnalizer; 
    ILogger logger; 

    public SomeClass(IStringAnalyzer stringAnalyzer, ILogger logger) 
    { 
     this.logger = logger; 
     this.stringAnalyzer = stringAnalyzer; 
    } 


    public void SomeMethod(string someParameter) 
    { 
     if (stringAnalyzer.IsValid(someParameter)) 
     { 
      logger.Log("Invalid string"); 
     }else 
     { 
      //do something with someParameter 
     } 
    } 
} 

は無効なパラメータを持つ工assのsomeMethodへのメソッド呼び出しは、ログを呼び出す場合ILoggerの文字列パラメータ "無効な文字列"を使用して あなたはではありませんこれらはエラーが発生する可能性があり、ユニットのテストであるため、IStringAnalyzerとILoggerの "実際の"実装を使用したいと思っています。あなたが本当にやっていることは、統合テストです。一度に1つしかテストしないのは、テストが失敗した場合、テストしている唯一のことが原因で失敗していることをすぐに知ることです。

このテストを適切に行うために、IStringAnalyzerとILoggerの2つの代替実装を用意する必要があります。彼らが何をする必要があるかに関して、これらの代替実装には違いがあります。 IStringAnalyzerの場合、欲しいのは、呼び出されたときにfalseを返し、テスト対象のメソッドがテストするコードパスを通過するようにするだけです。実際には、パラメータの値(someParameter)は気にしません。

ILoggerのログメソッドでは、呼び出されたことを知りたいし、 "無効な文字列"で呼び出されたので、テストでこれをアサートすることができます。

IStringAnalyzerとILoggerのこれらの2つの代替実装は、どちらも「偽」と呼ばれます(外部依存関係を偽造するため)。一方はスタブ(IStringAnalyzer)で、もう一方はモック(ILogger)です。スタブは、テストに必要な場所に移動するためのものです(この場合、IStringAnalyzerのIsValidメソッドはfalseを返します)。外部依存関係とのやりとりが適切に行われたかどうか(この場合はILogger)を確認することができます。テストスパイ(私の意見では無限に良い名前)としてモック(またはこのタイプのモック)を参照する人もいます。そして、はい、他のタイプのモックがあります(私はそれらを使ったことはありません)。これは、従来のコードフォームMichael FeathersとRoy Osheroveの単体テストの技術を使って作業することです。

次の例のように、「手で」スタブとモックを作成することができます。

class StringAnalyzerStub : IStringAnalyzer 
{ 
    public bool whatToReturn; 

    public StubStringAnalyzerStub(bool whatToReturn) 
    { 
     this.whatToReturn = whatToReturn; 
    } 

    public bool IsValid(string parameter) 
    { 
     return whatToReturn; 
    } 
} 


class LoggerMock : ILogger 
{ 
    public string WhatWasPassedIn; 

    public void Log(string message) 
    { 
     WhatWasPassedIn = message; 
    } 
} 

そして、ここではテストです:

[Test] 
public void SomeMethod_InvalidParameter_CallsLogger 
{ 
    IStringAnalyzer s = new StringAnalyzerStub(false); //will always return false when IsValid is called 
    ILogger l = new LoggerMock(); 
    SomeClass someClass = new SomeClass(s, l); 

    someClass.SomeMethod("What you put here doesnt really matter because the stub will always return false"); 

    Assert.AreEqual(l.WhatWasPassedIn, "Invalid string"); 
} 

手でこれを行うことについての事は、それが誤りであるということですメンテナンスが難しく、Rhino Mockのような分離フレームワークが必要です。彼らはここに(シンタックスを主張し、行為、アレンジを使用して)同じテストをRhinoのモックを使用して次のようになります方法です、あなたが動的にこれらのモックとスタブを作成することができません:

[Test] 
public void SomeMethod_InvalidParameter_CallsLogger 
{ 
    Rhino.Mocks.MockRepository mockRepository = new Rhino.Mocks.MockRepository(); 
    IStringAnalyzer s = mockRepository.Stub<IStringRepository>(); 
    s.Expect(s => s.IsValid("something, doesnt matter").IgnoreParameters().Return(false); 
    ILogger l = mockRepository.DynamicMock<ILogger>(); 
    l.Log("Invalid string"); 
    SomeClass someClass = new SomeClass(s, l); 
    mockRepository.ReplayAll(); 

    someClass.SomeMethod("What you put here doesnt really matter because the stub will always return false"); 

    l.AssertWasCalled(l => l.Log("Invalid string")); 
} 

自身の観点で定義された用語:)

免責事項:これはテキストエディタですべて書きましたので、コードに構文エラーがある可能性があります。

関連する問題