2012-01-18 14 views
2

私は変更できないコードがあります。理想的には、Publishメソッドを別のクラスに移動します。嘲笑は些細な操作になるだろう、と私は良いだろう。ここでは簡単な例を示します。私が何をしたいかMoq - 同じクラスの2つの関数を呼び出す、実際には1つ、模倣されたもの

public class Entity 
{ 
    private IController _controller; 

    // Omitted: Constructor where IController is assigned 

    public virtual int Process() 
    { 
    return Publish(_controller.DoSomeStuff()); 
    } 

    public virtual int Publish(int val) 
    { 
    Console.WriteLine(val); // This is actually a call to an external system. 
    return val; 
    } 
} 

は本当のプロセスメソッドを呼び出すと嘲笑方法を公開しています。 _controllerの値もまた嘲笑されます。

私はMOQを使ってやってみました:

var mock = new Mock<IController>(); 
mock.Setup(m => m.DoSomeStuff()).Returns(11); 

var mock2 = new Mock<Entity_Accessor>(); 
mock2.CallBase = true; 
mock2.Setup(a => a.Publish(It.IsAny<int>())).Returns(999); 
mock2.Object._controller = mock.Object; 

int result = mock2.Object.Process(); 
Assert.AreEqual(999, result); 

私はこのテストを実行すると、11の値は、私は本当のmock2.CallBase =を削除した場合、クラス全体が返す嘲笑される代わりに、999の返されますすべての関数のデフォルト値。

この場合、Processの元の実装を保持したままでPublishメソッドだけを模擬することはできますか?

TypemockやJustmockではない別の模擬フレームワークで上記を達成することは可能ですか(顧客が模擬ツールの複数のコピーに対して請求書を出しているかどうかは不明です)。

ありがとうございました!

答えて

5

あなたはモックを使用すべきではないProcess方法の機能をテストしようとしている場合は、期待値を返し、その後、確認するために、クラスの実際のインスタンスを使用してIControllerインタフェースとモックDoSomeStuffをからかっする必要がありますProcessはその値を正しく処理します。

Entityクラスを模擬しようとしているだけの場合は、IControllerをモックする必要はありません。あなたのメソッドをEntityクラスに偽装し、あなたが望むものを返すようにしてください。

更新:

あなたがテストしているクラスの一部を模擬する必要はありません。おそらく、外部システムへの参照を渡して、それをモックできるようにする必要があります。 Publishのコードが外部システムを直接呼び出す責任がある場合を除きます。これが推奨されるアプローチです。ただし、外部システムを直接呼び出すPublishメソッドの場合は、別のアプローチを採用し、統合テストを行う必要があります。

通常、統合テストはユニットテストと比較して速く実行されるものではなく、すべてのシステム対話が起動して実行されている必要があります。また、ほとんどの場合、あなたは物事を嘲笑することはありません。これは獣の性質なので、このようなプロセスを回避しないことを強くお勧めします。

+0

リストされている処理方法は大幅に簡略化されています。処理の良いビットがそこに続きます。私がしたいのは、Processメソッドだけをテストすることです。私はテストメッセージを公開したくないので、Publishメソッドをスタブにしたい。私はすでにIControllerインターフェイスを模擬することができます。私ができないことは、Publishメソッドを模倣することです。 – user1156891

+0

@ user1156891 - あなたのコメントに基づいて自分の答えを更新しました –

2

あなたのクラスは封印されているとは言いませんでしたので、この特定のシナリオ用にテスト可能なバージョンを作成することを検討する必要があります(一部をモックし、 :

public class TestableEntity : Entity 
{ 
    internal int PublishReturnValue { get; set; } 

    public override int Publish(int value) 
    { 
     return PublishReturnValue; 
    } 
} 

あなたはまだ規則的にProcessメソッドをテストすることができますこの方法で、まだあなたはモックもう一方の種類のことができます必要がs内のクラスを

var controllerMock = new Mock<IController>(); 
controllerMock.Setup(m => m.DoSomeStuff()).Returns(11); 
// assuming appropriate ctors 
var testableEntity = new TestableEntity(controllerMock); 
testableEntity.PublishReturnValue = 999; 

var result = testableEntity.Process(); 

Assert.AreEqual(999, result);   

注意をテストすることuchの方法は、いくつかのリファクタリング作業の兆候かもしれません。

+0

それは良い考えです。私は、リファクタリングを行う予定に時間を取れない場合、それを試すことがあります。 – user1156891

+0

@ user1156891:チャンスがあれば、チャールズ・ランバートの提案(依存関係のリファクタリング)を行ってください。私が提案したソリューション(* extract&override *)は、テストしているコードを変更できないときには一般的に便利です。がんばろう! –

関連する問題