1

プレゼンテーションクラスの単体テストをMVPパターンで書いていますが、モックセットアップコードを書くのに問題があります。

私はプレゼンターを持っていて、ビューをテストしたいというプレゼンターのLoadメソッドは、クラスプロパティ、テーブルフィールド、データ型をロードし、プレゼンターを設定する必要があります。テストすることを期待しています。そして、テストは毎回大きくなっています。

    [Test]
    public void When_Presenter_Loads_View_Should_Display_Selected_Class_Properties()
    {
        IList<string> dataTypes =new List<string>();
        IClassGenerationView view = mockRepository.StrictMock<IClassGenerationView>();
        tableRepository = mockRepository.Stub<ITableRepository>();

        using(mockRepository.Record())
        {
            SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes);
            view.Presenter = null;
            LastCall.IgnoreArguments();
            view.DataTypes = dataTypes;
            view.Show();

            view.ClassProperties = classProperties;
            view.TableName = "Table";
            view.Table = table;
            LastCall.IgnoreArguments();
        }


        using(mockRepository.Playback())
        {
            ClassGenerationPresenter presenter = new ClassGenerationPresenter(view, clazz,  tableRepository);
            presenter.Load();
        }
    }

このコードにコードの臭いはありますか?どうすればこれを改善または簡素化できますか?

4

2 に答える 2

2

私は何年もこれに苦労してきました。最初は MVP パターンを使用していましたが、後でプレゼンテーション モデル (WPF/Silverlight の MVVM に似ています) に切り替えました。とにかく、特に UI が急速に変化するアジャイル プロジェクトでは、結果は決して満足のいくものではありませんでした。そのため、これらのタイプのクラスのテストはもう作成せず、SpecFlow/WaTiN に切り替えて、まだ保守可能な自動化された UI テストを作成しています。詳細については、こちらをご覧ください: http://www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application

それでも UI ロジックのテストを書きたい場合は、セットアップ メソッドを使用してテストから一部のものを削除することは絶対にありません。上下にブラウズしなくても、テストの原因と結果を理解できることが不可欠です。代わりに、このブログ投稿で説明したように、BDD スタイルの単体テストを使用して ください。

一般に、私はこれらの BDD スタイルのテストを本質的に非常に組織化されたクラスに使用し、より AAA スタイルのテストを通常のクラスに使用します。

于 2012-01-31T19:41:11.207 に答える
1

長い眠れない夜と研究の後、私はこの解決策を見つけました.慎重に考えたとき、私はこれを思いつきました. 1 つのテストであまりにも多くの動作をテストしています。そして、私はこのようにテストを変更しました

[TestFixture]
public class When_Presenter_Loads
{
    private MockRepository mockRepository;
    private ITableRepository tableRepository;
    private IClass clazz;
    private Dictionary<string, Type> properties;
    private IClassGenerationView view;
    private ClassGenerationPresenter presenter;

    [SetUp]
    public void Setup()
    {
        mockRepository =new MockRepository();
        properties = new Dictionary<string, Type>();

        clazz = mockRepository.DynamicMock<IClass>();
        view = mockRepository.DynamicMock<IClassGenerationView>();
        tableRepository = mockRepository.Stub<ITableRepository>();


    }

    [Test]
    public void View_Should_Display_Class_Properties()
    {
        using(mockRepository.Record())
        {
            SetupResult.For(clazz.Properties).Return(properties);
            view.ClassProperties = properties;
        }

        using(mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }

    [Test]
    public void View_Should_Display_Class_Name_As_A_Table_Name()
    {
        using (mockRepository.Record())
        {
            SetupResult.For(clazz.Name).Return("ClassName");
            view.TableName = "ClassName";
        }

        using (mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }

    [Test]
    public void View_Should_Display_SQL_Data_Types()
    {
        List<string> dataTypes = new List<string>();

        using(mockRepository.Record())
        {
            SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes);
            view.DataTypes = dataTypes;
        }

        using(mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }

    [Test]
    public void View_Should_Show_Table()
    {
        using (mockRepository.Record())
        {
            SetupResult.For(clazz.Name).Return("ClassName");
            view.Table = null;
            LastCall.IgnoreArguments();
        }

        using (mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }
}

一度に 1 つの動作をテストするために、多くの動的モックを使用しました。また、これに関する Dave のOne Mock Per Testの記事を読むこともできます。

于 2009-01-02T13:00:47.060 に答える