5

オブジェクトのさまざまなプロパティに必要な値があることをアサートしたい MSTest (VS 2012) 単体テストがあります。これを行うには多くの方法があります。ただし、私の主な懸念は、新しいプロパティがオブジェクトに追加された場合、期待する値が含まれていることを確認するために単体テストを更新するのを見落としがちだということです。

私が考えることができる 1 つのことは、リフレクションを使用してオブジェクトのパブリック プロパティを列挙し、ユニット テストでアサートされたプロパティを追跡し、最後にチェックされなかったプロパティがあるかどうかをアサートすることです。

誰かがすでに似たようなことを書いていますか?

より良いアイデアはありますか?

更新: 問題のオブジェクトは、そのオブジェクトのデータを更新する他のクラス/メソッドがあるデータ転送オブジェクトのようなものであることを指摘しておく必要があります。これらのクラス/メソッドのテストを更新して、オブジェクトのすべてのプロパティを考慮していることを確認するのは簡単です。オブジェクトを右クリックして参照を見つけ、コードを確認するよりも、もう少し強力な (つまり、忘れたり見落としたりできない) ものが必要です。

例えば:

public class Person {
  public string FirstName;
}

public Person GetPerson() {}

[TestMethod]
public void GetPerson_ReturnsFilledInPerson()
{
    var actual = target.GetPerson();
    Assert.IsNotNull(actual.FirstName);
    // If somebody later adds LastName to Person, 
    // we want this unit test to fail until the LastName is checked too.
}

ありがとう、

ダン

4

1 に答える 1

1

あなたが求めたものは不合理ではありません。ドメイン クラスから DTO への単純なマッピングには、Automapper などのフレームワークを使用できます。ドメイン クラス A が dto ADto にマップされることを伝えるだけで、構成よりも規則を使用してプロパティをマップします。フレームワークには、すべてのマッピングが完了したことをテストする方法も付属しています。呼び出すことができMapper.AssertConfigurationIsValid();、Dto のすべてのプロパティがドメイン クラスのプロパティにマップされていることを確認します (コードで明示的に、または同じプロパティ名を持つことによって暗黙的に)。

つまり、基本的に同じことをしようとしているので、非常に有効なシナリオです。Automapper を使用しないことを選択したとしましょう。コードに別のものがないと推測していmapperます(その場合、リフレクションを使用してマッパークラス/コードをテストできます)。すべての DTO が別の IDto を返す DeepCopy メソッドを実装する同様のことを行いました。しかし、実際の型を呼び出し型と同じにしたい

    [Test]
    public void DeepCopyReturnsSameTypeAsOriginal()
    {
        var iDtoType = typeof (IDto);
        var allIDtoTypes = iDtoType.Assembly.GetTypes().Where(t => iDtoType.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract).ToList();

        foreach (var currentIDtoType in allIDtoTypes)
        {
            var instanceOfDtoType = (IDto)Activator.CreateInstance(currentIDtoType);
            var deepCopyType = instanceOfDtoType.DeepCopy();
            Assert.AreEqual(instanceOfDtoType.GetType(), deepCopyType.GetType(), 
                                string.Format("Deep Copy of Type '{0}' does not return the same Type. It returns '{1}'. The DeepCopy method of IDto should return the same type.",
                                instanceOfDtoType.GetType(), deepCopyType.GetType()));
        }
    }

同様のロジックを使用して、人物オブジェクトを取得できます。person オブジェクトのすべてのパブリック プロパティを取得し、それらを反復処理して、返された具体的な person オブジェクトにその特定のプロパティの非 null 値が含まれていることをアサートします。

ただし、この場合、テストは、すべてのプロパティに null 以外の値が必要であることがわかっている非常に特定のオブジェクトでのみ使用する必要があります。たとえば、値の種類で、AccountBalance プロパティが 0 を返す場合、その人の残高は 0 ですか、それともプロパティが設定されていませんか? 個人が null のメール プロパティを持っている場合、それはマッピングされていないことを意味するのでしょうか、それともシステム内にその人のメールが存在しないだけなのでしょうか。これが、特定のマッパー クラスがあるか Automapper を使用している場合、「これに値があるか」ではなく、マッピングが存在することをより具体的にテストする理由です。

さらに別のオプションは、null にすることはできず、カスタム属性でマップする必要があることがわかっているプロパティを装飾することです。例えば

Public class PersonDto {
    [TestNotNull]
    public string FirstName { get; set}

}

次に、単体テストでリフレクションを使用して、この属性を持つすべてのプロパティを検索し、それらが null でないことを確認できます。しかしもちろん、別のレベルで解決しようとしている同じ問題に出くわすこともあります。人々が重要なフィールドをマッピングするのを忘れるのではないかと心配している場合、カスタム属性でこれらのフィールドを装飾することを忘れないという保証はありません。

もちろん、プロパティがマップされていることをテストするのではなく、プロパティが存在することだけをテストしたい場合があります。その場合、リフレクションを使用してドメイン オブジェクト タイプのすべてのプロパティのリストを取得し、それぞれが DTO オブジェクト タイプのプロパティ リストに存在することを確認します。ただし、これはプロパティ自体がマップされていることをテストするのではなく、それらが存在することのみをテストします。Automapper とそのAssertConfigurationIsValid()テストを使用する場合は、DTO 内の各プロパティが適切にマップされていることをテストしますが、ドメイン内の各プロパティが DTO 内に関連付けられたプロパティを持っていることはテストしません。

あなたの質問に答えるには、プロパティが存在することと、適切にマップされていることの両方をテストしたい場合は、2 つのテストが必要です。1 つはドメイン オブジェクト タイプを Dto オブジェクト タイプと比較し、一方のプロパティが他方に存在することを確認するテストで、もう 1 つは DTO 内のすべてのプロパティが何かにマップされていることを確認するテストです (マッピングを行っているかどうかに関係なく)。独自のコードで使用するか、Automapper などのフレームワークを使用します)。

于 2013-03-21T23:48:55.583 に答える