8

抽象ファクトリ実装が与えられた場合:

public class FooFactory : IFooFactory {
   public IFoo Create(object param1, object param2) {
      return new Foo(param1, param2);
   }
}

このクラスにはどの単体テストが作成されますか?param1とparam2がFooの作成に転送されたことを確認するにはどうすればよいですか?Fooのこれらの公共施設を作成する必要がありますか?それはカプセル化を破っていませんか?それとも、これを統合テストに任せるべきですか?

4

5 に答える 5

11

このようなファクトリ( xUnit.netを使用)のいくつかの単体テストの1つを作成する方法は次のとおりです。

[Fact]
public void CreateReturnsInstanceWithCorrectParam1()
{
    var sut = new FooFactory();
    var expected = new object();
    var actual = sut.Create(expected, new object());
    var concrete = Assert.IsAssignableFrom<Foo>(actual);
    Assert.Equal(expected, concrete.Object1);
}

カプセル化を破りますか?はい、いいえ...少し。カプセル化とは、データを隠すことだけではありません。さらに重要なことは、オブジェクトの不変条件を保護することです

FooがこのパブリックAPIを公開していると仮定しましょう:

public class Foo : IFoo
{
    public Foo(object param1, object param2);

    public void MethodDefinedByInterface();

    public object Object1 { get; }
}

プロパティはデメテルObject1の法則にわずかに違反していますが、読み取り専用であるため、クラスの不変条件を混乱させることはありません。

さらに、Object1プロパティは具体的なFooクラスの一部であり、IFooインターフェイスではありません。

public interface IFoo
{
    void MethodDefinedByInterface();
}

緩く結合されたAPIでは、具象メンバーが実装の詳細であることに気付くと、そのような具象のみの読み取り専用プロパティがカプセル化に与える影響は非常に小さくなります。このように考えてください:

パブリックFooコンストラクター具象FooクラスのAPIの一部であるため、パブリックAPIを調べるだけで、それを学習しparam1param2クラスの一部になります。ある意味で、これはすでに「カプセル化を破る」ので、各パラメーターを具象クラスの読み取り専用プロパティとして使用可能にすることはあまり変わりません。

このようなプロパティは、工場から返されるFooクラスの構造形状を単体テストできるという利点を提供します。

これは、具体的なFooクラスをすでにカバーしていると想定しなければならない一連の動作ユニットテストを繰り返すよりもはるかに簡単です。これは、ほとんど論理的な証明のようなものです。

  1. 具体的なFooクラスのテストから、コンストラクターパラメーターを正しく使用/相互作用することがわかります。
  2. これらのテストから、コンストラクターパラメーターが読み取り専用プロパティとして公開されていることもわかります。
  3. FooFactoryのテストから、具象Fooクラスのインスタンスが返されることがわかります。
  4. さらに、Createメソッドのテストから、そのパラメーターがFooコンストラクターに正しく渡されることがわかります。
  5. QED
于 2012-02-03T07:35:20.633 に答える
2

まあ、おそらくそれらのパラメータは、返さIFooれたものにそれについて何か真実を持たせます。返されたインスタンスについてそれが正しいかどうかをテストします。

于 2012-02-02T23:37:30.533 に答える
0

FooFactoryをパラメーターとしてFooを期待するジェネリッククラスにし、それをモックとして指定することができます。次にfactory.Create(...)を呼び出すと、モックのインスタンスが作成され、モックが期待した引数を受け取ったことを確認できます。

于 2012-02-02T23:25:19.910 に答える
0

これは、Fooが2つの入力オブジェクトをどのように処理するかによって異なります。Fooが彼らに対して行っていることで、簡単に問い合わせることができるものがないか確認してください。たとえば、オブジェクトでメソッド(ゲッターまたはセッターを含む)が呼び出された場合は、期待されるものが呼び出されたことを確認できるモックまたはスタブを提供します。IFooにテストできるものがある場合は、作成後にモックオブジェクトを介して既知の値を渡してテストすることができます。オブジェクト自体が公開されている必要はなく、オブジェクトが通過したことを確認できます。

また、テストされた他の動作がIFoo実装間の違いに依存するかどうかに応じて、期待されるタイプ(Foo)が返されることを確認する場合もあります。

結果として発生する可能性のあるエラー条件がある場合は、それらも強制しようとします。一方または両方のオブジェクトに対してnullを渡すとどうなりますか。もちろん、Fooは個別にテストされるため、 FooFactoryは、Fooがすべきことを実行することをテストします。

于 2012-02-02T23:33:05.023 に答える
0

少なくとも私の経験によれば、工場は通常ユニットテストされていません-ユニットテストにはあまり価値がありません。それはそのインターフェース実装マッピングの実装であるため、具体的な実装を参照します。そのため、モックFooは、渡されたパラメータを受け取るかどうかをチェックすることはできません。

一方、通常、DIコンテナはファクトリとして機能するため、DIコンテナを使用している場合は、ファクトリは必要ありません。

于 2012-02-02T23:33:53.197 に答える