テスト用のプライベートセッターによるプロパティのスタブ


10

オブジェクトがあります

public class MyObject{
    protected MyObject(){}

    public string Property1 {get;private set;}
    public string Property2 {get;private set;}
    public string Property3 {get;private set;}
    public string Property4 {get;private set;}
    public string Property5 {get;private set;}
    public string Property6 {get;private set;}
    public string Property7 {get;private set;}
    public string Property8 {get;private set;}
    public string Property9 {get;private set;}
    public string Property10 {get;private set;}
}

本番コードでは、オートマッパーを介してこのオブジェクトを設定します。プロパティにアクセスして正しく設定できます。

今後、このクラスを将来のパイプラインでテストする場合、プロパティに対してダミー値(テスト対象)を設定することはできません。

利用可能なオプションがいくつかあります。

  • テストに必要なパラメーターを受け入れ、プロパティを設定するカスタムコンストラクター。現在、3つのコンストラクターが必要です。コンストラクタはビジネス機能を提供しないため、これはクリーンではありません。

  • プロパティを仮想化して、クラスをスタブできるようにします。しかし、プロパティを仮想にマークしても、ビジネス上の価値はなく、クラスを汚染します。

  • オブジェクトビルダーをクラスに追加して、内部でオブジェクトを構築します。この場合も、ビジネスに付加価値はありません。おそらく少しクリーンですが、ドメインオブジェクト内の関連性のないコードがまだたくさんあります。

ここに提案、アドバイス、または代替オプションがありますか?

回答:


8

いくつかのオプションがあります。

  • 先に進んで、カスタムコンストラクター、仮想プロパティ、またはオブジェクトビルダーを使用してください。これの背後にある理論的根拠は、オブジェクトが独立しているべきであり、オートマッパーのような魔法に依存してはならないということです。何らかの魔法が起こっていない限り、完全に役に立たないクラスは、クラスをあまりよく考えていません。「ビジネス価値」だけが優れたデザインの決定要因ではありません。

  • テストプロセスにオートマッパーを含めます。これはもはやユニットテストではないと言う人もいます。それはどうでもいい事です。単体テストは唯一の種類のテストではありません。

  • 特にテスト用にオートマッパーの機能を提供するものを実装します。プロパティ名と値を含むディクショナリからオブジェクトを生成するためにリフレクションを使用する小さなユーティリティを簡単に作成できます。

また、この質問と回答を見てください。テスト用にプライベートなものを内部/パブリックにするか、PrivateObjectのようなハックを使用しますか?


3

このようなことをテストでリフレクションを使用することをためらわない。

間違った理由でコードを変更するので、モックを仮想化するのは嫌いです。

私はオートマッパーを知りませんが、テストに含めることは良い考えであると@Mikeに同意します。単体テスト/統合テストの区別はあまり興味深いものではありません。確かに、テストスイートが大きくなって遅くなっている場合は、すべてのテストの賢明なサブセットのみを最高の頻度で実行するために、フィルタリングと分類を行う必要があります。

リフレクションを使用したサンプルハック、nameof()を使用した場合のパフォーマンスは向上しますが、型を失うことになります。

public static class TestExtensions
{
    public static void SetProperty<TSource, TProperty>(
        this TSource source,
        Expression<Func<TSource, TProperty>> prop,
        TProperty value)
    {
        var propertyInfo = (PropertyInfo)((MemberExpression)prop.Body).Member;
        propertyInfo.SetValue(source, value);
    }
}

0

単体テストの目的で、Microsoft Fakes、TypeMock、JustMockなどのモックフレームワークを使用して、プライベートメンバーのモックをサポートします。

Smocks(利用可能な@nugetパッケージ)もご覧ください。Smocksの制限は、プライベートメンバーへのアクセスを提供しないことです。しかし、静的メンバーと非仮想メンバーをモックする機能があります。また、無料でご利用いただけます。

別の最も簡単な方法は、PrivateObject / PrivateTypeを使用することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.