質問
別のメソッド内から呼び出されたメソッドの結果を偽装する方法を見つけようとしています。
別のヘルパーを呼び出してデータを取得し、それを変換する「LoadData」メソッドがあります(変換された結果をテストすることに興味があります)。
したがって、次のようなコードがあります:
public class MyClass(){
public void LoadData(){
SomeProperty = Helper.GetSomeData();
}
public object SomeProperty {get;set;}
}
Helper.GetSomeData() メソッドからの既知の結果が必要です。モック フレームワーク (Rhino モックの経験はかなり限られていますが、何でも受け入れます) を使用して、期待される結果を強制することはできますか?もしそうなら、どのようにして?
*編集 - はい、予想通り、望んでいたハックを達成できませんでした。データを設定するより良い方法を考え出す必要があります。
解決
私の知る限り、Helper オブジェクトのインターフェイスまたは基本抽象クラスを作成する必要があります。Rhino Mocks を使用すると、必要な値を返すことができます。
あるいは、通常は Helper オブジェクトから取得するデータをパラメーターとして受け入れる LoadData のオーバーロードを追加することもできます。これはさらに簡単かもしれません。
他のヒント
そこに問題があります。これがコードの単純化されたシナリオであるかどうかはわかりませんが、Helper クラスがそのように使用されている場合、コードはテストできません。まず、Helper クラスが直接使用されるため、 モックに置き換えることはできません. 。次に、静的メソッドを呼び出しています。C# についてはわかりませんが、Java では 静的メソッドをオーバーライドできません.
ダミーの GetSomeData() メソッドを使用してモック オブジェクトを挿入できるようにするには、いくつかのリファクタリングを行う必要があります。
この簡略化されたバージョンのコードでは、明確な答えを与えるのは困難です。いくつかのオプションがあります:
- Helper クラスのインターフェイスを作成し、クライアントが MyClass クラスに Helper 実装を注入する方法を提供します。しかし、Helper が実際には単なるユーティリティ クラスである場合、それはあまり意味がありません。
- MyClass に getSomeData という保護されたメソッドを作成し、Helper.LoadSomeData のみを呼び出すようにします。次に、LoadData 内の Helper.LoadSomeData への呼び出しを getSomeData への呼び出しに置き換えます。これで、getSomeData メソッドをモックしてダミー値を返すことができます。
単純にヘルパー クラスへのインターフェイスを作成することに注意してください そしてそれをメソッド経由で注入します。これにより、実装の詳細が公開される可能性があります。クライアントが実装を提供する必要がある理由 ユーティリティ 単純な操作を呼び出すクラス?これにより、MyClass クライアントの複雑さが増加します。
持っているものを次のようなものに変換することをお勧めします。
public class MyClass()
{
private IHelper _helper;
public MyClass()
{
//Default constructor normal code would use.
this._helper = new Helper();
}
public MyClass(IHelper helper)
{
if(helper == null)
{
throw new NullException(); //I forget the exact name but you get my drift ;)
}
this._helper = helper;
}
public void LoadData()
{
SomeProperty = this._helper.GetSomeData();
}
public object SomeProperty {get;set;}
}
これで、クラスは依存関係の注入と呼ばれるものをサポートするようになりました。これにより、ヘルパー クラスの実装を注入できるようになり、クラスがインターフェイスにのみ依存するようになります。これをモックするときは、IHelper インターフェイスを使用するモックを作成し、それをコンストラクターに渡すだけで、クラスはそれを実際の Helper クラスであるかのように使用します。
Helper クラスを静的クラスとして使用することに行き詰まっている場合は、プロキシ/アダプター パターンを使用し、IHelper インターフェイスをサポートする別のクラス (これも作成する必要があります) で静的クラスをラップすることをお勧めします。
ある時点でこれをさらに一歩進めたい場合は、改訂されたクラスからデフォルトのヘルパー実装を完全に削除し、IoC (制御の反転) コンテナを使用できます。ただし、これが初めての場合は、まず、この余分な手間すべてに価値がある理由の基本に焦点を当てることをお勧めします (これは私見です)。
単体テストは次の疑似コードのようになります。
public Amazing_Mocking_Test()
{
//Mock object setup
MockObject mockery = new MockObject();
IHelper myMock = (IHelper)mockery.createMockObject<IHelper>();
mockery.On(myMock).Expect("GetSomeData").WithNoArguments().Return(Anything);
//The actual test
MyClass testClass = new MyClass(myMock);
testClass.LoadData();
//Ensure the mock had all of it's expectations met.
mockery.VerifyExpectations();
}
ご質問がございましたら、お気軽にコメントしてください。(ちなみに、このコードがすべて機能するかどうかはわかりません。ブラウザに入力しただけです。主に概念を説明しています。)
コードのリファクタリングを強制せずにメソッド呼び出しを「偽装」できる Typemock Isolator を調べてみるとよいでしょう。私はその会社の開発者ですが、デザインを変更しない(またはテスト能力のために変更しないことを強制されないように強制しないようにすることを選択したい場合、ソリューションは実行可能です。www.typemock.comにあります
ロイブログ:ISerializable.com
はい、モック フレームワークはまさにあなたが探しているものです。特定のモックアウト/スタブ化されたクラスをどのように返すかを記録/調整できます。
Rhino Mocks、Typemock、および Moq はすべて、これを行うための優れたオプションです。
スティーブン・ウォルサーの投稿 Rhino Mocks の使用については、Rhino Mocks を初めて使ったときに非常に役に立ちました。
私なら次のようなことを試してみます。
public class MyClass(){
public void LoadData(IHelper helper){
SomeProperty = helper.GetSomeData();
}
このようにして、たとえば MOQ を使用してヘルパー クラスをモックアップできます。