1

と呼ばれるすべてのユーザー入力を含むクラスを作成するプレゼンターにメソッドがありますUserInputEntity。インターフェイスを実装しますIUserInputEntity。現在、タイプのローカル変数として宣言しているためUserInputEntity、次のメソッドでモックすることはできません(簡潔にするために簡略化しています)。

public void CompletionReportNotifier(object sender, VerificationStatusEventArgs e)
{
    _view.PermanentCsvFileVerificationCancellation = null;

    string logMessage;
    bool inputsVisible = false;

    //Mocking inputs.NumberOfErrorsFound??
    if (e.CarriedOutToCompletion != true || inputs.NumberOfErrorsFound > 0)
    {
        inputsVisible = true;
        _view.VerificationCompleted = false;
        logMessage = "failed to complete operation";
    }
    else
    {
        _view.VerificationCompleted = true;
        logMessage = "Completed operation";
    }
    _view.UIUpdate(logMessage, inputsVisible);
}

これを回避する最も適切な方法は何ですか? 私が考えることができる唯一の解決策は、エンティティ クラスのコンストラクターのみを呼び出し、IUserInputEntity. inputs次に、プレゼンターの の宣言を type に変更しIUserInputEntityます。これは適切でしょうか、それともより良い方法がありますか?

以下は、のインスタンスがinputs現在作成されているメソッドのコピーです (簡略化)。

private void DataVerification(Object sender, EventArgs e)
{
    if (_view.VerifyingData != true)
    {
        inputs = new UserInputEntity(_view.DataTypeInputs, _view.ColumnNameInputs, _view.InitialRow, _view.FinalRow, _view.CurrencyPair, _view.CsvFilePath, _view.ErrorLogFilePath);

        // ...

        verification.VerifyDataTypesAsync();     
    }
    else
    {
        _view.PermanentCsvFileVerificationCancellation.Cancel();
    } 
}
4

3 に答える 3

1

依存性注入パターンに従う場合、キーワード「new」を使用する場合は、細心の注意と恐れを持って対処する必要があります。注入する必要がある依存関係の 1 つである可能性は非常に高いです。これは間違いなくそれらの時間の1つです。

ここでの実際の解決策はIUserInputEntity、コンストラクターに追加し、それを抽象化して、コントロール コンテナー (StructureMap、NInject など) の反転を自動的に挿入することです。構造マップでは、これは次のようになります。

public class DependencyRegistry : Registry
{
    public DependencyRegistry()
    {
        For<IUserInputEntity>().Use<UserInputEntity>();
    }
}

クラスの使用法:

public MyClass(IUserInputEntity userInputEntity)
{
   _userInputEntity = userInputEntity;
}

次に、既知のプロパティを設定するか、具体的なクラスで自由に使用できます。テストでは、次のようになります (NUnit と RhinoMocks を想定):

[Test]
public void MyTest()
{
   var mockEntity = MockRepository.GenerateMock<IUserInputEntity>();

   var testedClass = new MyClass(mockEntity);
}

この時点で、RhinoMocks で提供されるさまざまな制御メソッドを使用して、またはモック フレームワークが何であれ、モック エンティティをトレーニングするために好きなことを行うことができます。ここで注意すべき重要なことは、具体的なUserInputEntity機能をどのようにプログラムしたかによって、その機能の具体的な実装を渡していないということです。あなたは、あなたが指示したことを正確に実行するモックを渡しています。

于 2012-08-27T16:07:19.090 に答える
1

ここで、ある時点で依存関係をモックする必要があります。この例の唯一の間違ったカップリングが、ビューで直接インスタンス化されている IUserInputEntity なのか、それとも_viewカップリングもエラーなのかを判断するのは非常に困難です。この例では_view、インターフェイスを実装するかどうかは示されていませんが、実装する必要があります。MVP パターンでは、プレゼンターがビューとモデルの間を仲介します。

IUserInputEntityビューがユーザー入力の収集を担当する場合は、プレゼンターがアクセスできるように、を返すビューのメソッドをモックする必要があります。私が主張するデータ検証は、モデル クラスに渡す必要があります (YYY が回答で使用している例を使用してください)。これで、モデルは任意のタイプの IView からの入力で検証できるようになりました。

したがって、ビューを更新IUserInputEntityして YYY の回答の as を取得し、プレゼンターを更新して DI を使用[IYourViewInterface]してビューからのさまざまなタイプの出力をシミュレートします。プレゼンターでこれらのインターフェイスを使用し、ビュー クラスとモデル クラスのコンストラクターで依存関係を取得して、アプリケーションのテスト容易性を最大化します。

于 2012-08-27T16:48:56.780 に答える
0

メソッドで作成されたオブジェクトのインスタンス。そのインスタンスをモックする方法は?

それが、ファクトリまたはプロバイダーの目的です。理想的には、ファクトリー/プロバイダーを注入して、返されるものを修正できるようにする必要があります。

これは、 が必要であることを前提としていnewます。そうでない場合 (つまり、ステートレス サービスである場合) は、単純にそのサービスを注入する必要があります。

最後のオプションであり、無視するものではありません: 本物のオブジェクトを使用してください。コラボレーターに含まれるロジックが複雑ではなく、依存関係がなく、オブジェクトがかなり馬鹿げていて、十分にテストされており、単に使用するだけでなくセットアップも簡単な場合は、それをモックするよりも大きな苦痛になります。

于 2012-08-28T13:05:40.263 に答える