-1

MVP アーキテクチャに切り替えて、テストしようとしています。プレゼンターの構成方法について質問があります。

public class Presenter
{
    public void onResume()
    {
        doA();
        doB();
        doC();
    }

    protected void doA() {};
    protected void doB() {};
    protected void doC() {};
}

public class MyScreen implements MyScreenView
{
    private Presenter presenter;

    public MyScreen()
    {
        presenter = new Presenter(this);
    }

    public OnResume()
    {
        presenter.OnResume();
    }
}

上記のコードでは、ビューが再開されると、ビューはプレゼンターの OnResume() を呼び出すだけです。プレゼンターは、doA()、doB()、および doC() の 3 つのメソッドを内部的に呼び出して、必要な処理を実行します。

または、次のようにビューで doA()、doB()、および doC() を直接呼び出すこともできます。

public class Presenter
{
    public void doA() {};
    public void doB() {};
    public void doC() {};
}

public class MyScreen implements MyScreenView
{
    private Presenter presenter;

    public MyScreen()
    {
        presenter = new Presenter(this);
    }

    public OnResume()
    {
        presenter.doA();
        presenter.doB();
        presenter.doC();
    }
}

私の質問は、2 番目のソリューションをテストする方が簡単だということです。プレゼンターは、個別の責任を持つ 3 つの個別のパブリック メソッドにきれいに分割されているため、プレゼンター用の 1 つのモノリシック テストではなく、doA、doB、および doC のテストを個別に作成できます。ソリューション 1 の onResume() メソッド。

最初の解決策では、onResume() のテストを作成する必要があります。これは、これら 3 つのメソッドを呼び出す責任があります。これは、他のプライベート関数を呼び出す関数よりも、個々の責任の小さな関数をテストする方がはるかに簡単であるため、テストが難しいことを意味します。ただし、2 番目のソリューションは、プレゼンターが何をしているかを知っているようで、最初のソリューションの onResume() メソッドでプレゼンターに実行させていないだけなので、良い MVP とは思えません。

4

2 に答える 2

1

MyScreen クラスを

public class MyScreen implements MyScreenView
{
    private presenter;

    public MyScreen()
    {
        presenter = new Presenter();
    }

    public MyScreen(Presenter p) 
    {
        presenter = p;
    }

    public OnResume()
    {
        presenter.OnResume();
    }
}

次に、新しいプレゼンターを作成する本番コンストラクターと、テスト用の便利なコンストラクターを用意して、モック プレゼンターでインスタンス化できるようにします。私はMockitoが好きです(メモリからのコードなので...)

Presenter mockP = Mock(Presenter.class);
MyScreen target = new MyScreen(mockP);
target.OnResume();
verify(mockP).doA();
verify(mockP).doB();
verify(mockP).doC();

ここでは、モック プレゼンターを使用して新しい MyScreen を作成します。さまざまなメソッドで verify を呼び出すと、そのメソッドがモックで呼び出されなかった場合、テストは失敗します。つまり、MyScreen クラスで OnResume を呼び出すと、そのプレゼンター フィールドで doA、doB、および doC を呼び出すことをアサートするテストを実際に作成しています。

メソッドが呼び出されたことを確認するときに期待する引数を指定できます。また、mockP のメソッドをスタブ化して、特定のシナリオで既知の結果を返すようにすることもできます。


ちなみに

public OnResume()
    {
        presenter.OnResume();
    }

presenter.OnResume()MyScreenクラスを変更せずにメソッドの動作を変更できるため、2つのオプションのより良い選択です。

于 2012-10-04T11:45:43.210 に答える
1

最初に My Screen クラスでプレゼンターを注入可能にします

public class MyScreen implements MyScreenView
{
    private presenter;

    public MyScreen()
    {
        presenter = this(new Presenter());
    }

    public MyScreen(Presenter p) 
    {
        presenter = p;
    }

    public OnResume()
    {
        presenter.OnResume();
    }
}

これで、モックを注入して MyScreen の動作をテストできます。

Presenter mockP = Mock(Presenter.class);
MyScreen target = new MyScreen(mockP);
target.OnResume();
verify(mockP).doA();
verify(mockP).doB();
verify(mockP).doC();

完全に別のテストで、プレゼンターをテストできます。

Presenter presenter = new Presenter();
presenter.onResume();
assertEquals("some State that should be true after calling on resume", presenter.getSomeMagicState());

onResume が doA、doB、および doC を呼び出していることをテストしないでください。プレゼンターの状態をチェックして、メソッドの動作をテストしてください。

doX が複雑になる場合は、それを別のクラスに抽出してテストし、プレゼンターに挿入して、呼び出されることをテストします。

于 2012-10-04T11:58:37.127 に答える