9

別のメソッド内から呼び出されたメソッドの結果を偽造する方法を見つけようとしています。

別のヘルパーを呼び出してデータを取得し、それを変換する「LoadData」メソッドがあります(変換された結果をテストすることに興味があります)。

だから私はこのようなコードを持っています:

public class MyClass(){
  public void LoadData(){
    SomeProperty = Helper.GetSomeData();
 }
 public object SomeProperty {get;set;}
}

Helper.GetSomeData() メソッドからの既知の結果が必要です。モッキング フレームワーク (Rhino Mocks の経験はかなり限られていますが、何に対してもオープンです) を使用して、期待される結果を強制することはできますか? もしそうなら、どのように?

*編集 - ええ、予想通り、私は望んでいたハックを達成できませんでした。データをセットアップするためのより良い方法を考え出さなければなりません.

4

6 に答える 6

10

そこに問題があります。それがコードの単純化されたシナリオかどうかはわかりませんが、ヘルパー クラスがそのように使用されている場合、コードはテストできません。まず、 Helper クラスが直接使用されるため、 mock に置き換えることはできません。次に、静的メソッドを呼び出しています。C# についてはわかりませんが、Java では静的メソッドをオーバーライドできません

ダミーの GetSomeData() メソッドを使用してモック オブジェクトを挿入できるようにするには、リファクタリングを行う必要があります。

この単純化されたバージョンのコードでは、率直な答えを出すのは困難です。いくつかのオプションがあります:

  • Helper クラスのインターフェイスを作成し、クライアントが Helper 実装を MyClass クラスに挿入する方法を提供します。しかし、Helper が単なるユーティリティ クラスである場合、あまり意味がありません。
  • MyClass で getSomeData という保護されたメソッドを作成し、Helper.LoadSomeData のみを呼び出すようにします。次に、LoadData 内の Helper.LoadSomeData への呼び出しを for getSomeData に置き換えます。これで、getSomeData メソッドをモックしてダミー値を返すことができます。

単純にヘルパー クラスへのインターフェイスを作成し、メソッドを介して注入することに注意してください。これにより、実装の詳細が公開される可能性があります。単純な操作を呼び出すために、クライアントがユーティリティクラスの実装を提供する必要があるのはなぜですか? これにより、MyClass クライアントの複雑さが増します。

于 2008-09-18T07:19:56.967 に答える
8

あなたが持っているものを次のように変換することをお勧めします:

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 インターフェイスを使用するモックを作成してコンストラクターに渡すだけで、クラスはそれを実際のヘルパー クラスであるかのように使用します。

ヘルパー クラスを静的クラスとして使用することに行き詰まっている場合は、プロキシ/アダプター パターンを使用し、静的クラスを 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();
}

ご不明な点がございましたら、お気軽にコメントしてください。(ちなみに、このコードがすべて機能するかどうかはわかりません。ブラウザに入力しただけです。主に概念を説明しています)。

于 2008-09-18T07:35:52.560 に答える
2

私の知る限り、ヘルパー オブジェクトのインターフェイスまたは基本抽象クラスを作成する必要があります。Rhino モックを使用すると、必要な値を返すことができます。

または、通常 Helper オブジェクトから取得するデータをパラメーターとして受け入れる LoadData のオーバーロードを追加することもできます。これはさらに簡単かもしれません。

于 2008-09-18T07:16:10.347 に答える
2

コードのリファクタリングを強制せずにメソッド呼び出しを「偽造」できる Typemock Isolator を調べることをお勧めします。私はその会社の開発者ですが、デザインを変更しないことを選択したい場合 (またはテスト容易性のために変更しないように強制された場合) のソリューションは実行可能です。www.Typemock.com にあります。

Roy ブログ: ISerializable.com

于 2008-09-19T01:22:50.640 に答える
0

はい、モッキング フレームワークはまさに​​あなたが探しているものです。特定のモックアウト/スタブ化されたクラスを返す方法を記録/配置できます。

Rhino Mocks、Typemock、および Moq はすべて、これを行うための適切なオプションです。

Rhino Mocks の使用に関するSteven Walther の投稿は、私が初めて Rhino Mocks を使い始めたときに大いに役立ちました。

于 2008-09-18T07:15:48.350 に答える
0

私はこのようなことを試してみます:

public class MyClass(){
  public void LoadData(IHelper helper){
    SomeProperty = helper.GetSomeData();
 }

このようにして、たとえば MOQ を使用してヘルパー クラスをモックアップできます。

于 2008-09-18T07:20:51.787 に答える