5

私はこれに似たドメインモデルを持つアプリに取り組んでおり、 a は a と a の両方からLineItem参照できます。OrderShipment

ダイアグラム

AutoFixture を使用して を生成している場合、 との両方にOrderの同じセットを使用するにはどうすればよいですか?LineItemsorder.LineItemsorder.Shipments*.ItemShipments*.LineItem

理論的には、次のテストに合格する必要があります。

var fullyShippedOrder = fixture.CreateAnonymous<Order>();
var shippedLineItems = fullyShippedOrder.Shipments
    .SelectMany(o => o.ItemShipment, (s, i) => i.LineItem)
    .Distinct();
Assert.EqualCollection(fullyShippedOrder.LineItems, shippedLineItems);

...テストに応じて、部分的に出荷された注文も生成できるようにしたいと思います。

(Order の項目と Shipment の項目は別のものであり、それらを表すために同じクラスを使用すべきではないという確固たる議論があります。しかし、私が扱っているデータは、レガシーシステムであり、それについてできることはあまりありません。)

4

1 に答える 1

5

あなたが言ったように、テストで発生している摩擦は、ドメイン モデルの設計上の問題の兆候である可能性が最も高いです。理想的には、テストを聞いて、問題を根本から解決する必要があります。ただし、この場合は実現不可能であるため、回避策を示します。

メソッドを使用して、固定された順序Fixtureから常にオブジェクトを返すように を設定できます。LineItemRegister<T>(Func<T> creator)

カスタマイズでパッケージ化された例を次に示します。

public class GenerateLineItemFromFixedSequence : ICustomization
{
    public void Customize(IFixture fixture)
    {
        var items = CreateFixedLineItemSequence(fixture);
        fixture.Register(() => GetRandomElementInSequence(items));
    }

    private static IEnumerable<LineItem> CreateFixedLineItemSequence(IFixture fixture)
    {
        return fixture.CreateAnonymous<LineItem[]>();
    }

    private static LineItem GetRandomElementInSequence(IEnumerable<LineItem> items)
    {
        var randomIndex = new Random().Next(0, items.Count());
        return items.ElementAt(randomIndex);
    }
}

テストのコンテキストでこの動作を適用するには、Fixtureオブジェクトにカスタマイズを追加するだけです:

fixture.Customize(new GenerateLineItemFromFixedSequence());

LineItem同様に、前述の部分的に出荷された注文のように、さまざまな状態のオブジェクトの固定シーケンスを生成する他のカスタマイズを作成し、それらをさまざまなテストで使用できます。

観察

アルゴリズム自体は作成されるオブジェクトのタイプと結合されていないため、このカスタマイズを汎用にすることができることに注意してください。これにより、効果的に戦略に変換されます。

したがって、汎用パラメーターを導入してカスタマイズを変更します。

public class GenerateFromFixedSequence<T> : ICustomization
{
    public void Customize(IFixture fixture)
    {
        var items = CreateFixedSequence(fixture);
        fixture.Register(() => GetRandomElementInSequence(items));
    }

    private static IEnumerable<T> CreateFixedSequence(IFixture fixture)
    {
        return fixture.CreateAnonymous<T[]>();
    }

    private static T GetRandomElementInSequence(IEnumerable<T> items)
    {
        var randomIndex = new Random().Next(0, items.Count());
        return items.ElementAt(randomIndex);
    }
}

さまざまなオブジェクトに使用できます。

fixture.Customize(new GenerateFromFixedSequence<LineItem>());
fixture.Customize(new GenerateFromFixedSequence<Order>());
fixture.Customize(new GenerateFromFixedSequence<Shipment>());
于 2012-12-19T09:52:37.713 に答える