[TestFixture]
public class TestAutoFixture4
{
[Test]
[AutoMoqData]
public void CreatingAnDummyObjectShouldNotThrow(IFixture fixture)
{
fixture.Invoking(x => x.Create<DummyObject>()).ShouldNotThrow();
}
[Test]
[AutoMoqData]
public void BuildingAnDummyObjectShouldNotThrow(IFixture fixture)
{
fixture.Invoking(x => x.Build<DummyObject>().Create()).ShouldNotThrow();
}
}
public class DummyObject
{
public Guid Id { get; set; }
public DummyObject CircularRef { get; set; }
}
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(new Fixture()
.Customize(
new DummyCustomization()
))
{ }
}
public class DummyCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<DummyObject>(c =>
c.Without(x => x.CircularRef)
);
}
}
AutoFixtureを3.50.6から4.0.0に更新しました。
上記のコードは3.50.6で完全に機能しますが、4.0.0(.NET 4.6.2、NUnit3.7.1、FluentAssertions 4.19.4)を使用して合格するのは最初のテスト(fixture.Createを使用)のみです。
挿入されたカスタマイズで循環参照を解決しないように指定されている場合でも、fixture.Buildを使用したテストは失敗します。
変更ログの何かを見逃しましたか、それともバグですか?
前もって感謝します :)
@ Dev-I-Antここに問題を投稿していただき、そのような詳細な説明をありがとうございます👍
この動作は、#781で適用された変更の結果です。 1つのカスタマイズが他のカスタマイズに影響を与える可能性がある場合の問題を修正しました。 これは、同じタイプに対して2つの後続のカスタマイズがある場合でも発生します。前のカスタマイズは、完全に無視されます。
Build<T>()
APIを使用すると、実際にはDummyObject
タイプの一時的なカスタマイズが作成されます。 つまり、以前のすべてのカスタマイズ( Customize<DummyObject>()
APIを介して適用)は無視され、参加しません。 そのため、循環依存に関するエラーが再び表示されます。
この種の分離が必要です。そうしないと、非常に奇妙な問題が発生する可能性があります(上記のPRで参照されている問題を参照してください)。 したがって、物事を単純にするために、観察された動作はバグではなく、現在の設計の特殊性であると言えます。
あなたが観察する問題を軽減するために、私は基本的に2つの方法を見ます。
Omitter
を追加しますすでに同様の質問があったので、ここで提案されて
Create<T>()
APIを使用するサンプルでは、 Build<>
APIを使用する必要はありません。 もちろん、単純化されたサンプルを提供し、実際にはそのAPIが必要な場合もあります。 ただし、万が一の場合に備えて、このオプションを提供することにしました😃
私の答えがこの問題に光を当てるのに役立ったかどうか教えてください😉
@zvirja洞察に感謝します、これは物事をより明確にします。
同じタイプでカスタマイズをスタックすることは(イライラしたとしても)不可能であるという事実についてはすでにたくさん読んでおり、この変更は確かに私にいくつかの問題を引き起こしますが、なぜあなたが何かを変更しなければならなかったのか理解しています。
私のユースケースは、多くの循環参照があるオブジェクトの大きなグラフを使用してアプリケーションをテストすることです。 親が子のリストを保持し、そのリストが親を参照する典型的な(アンチ?)パターン。
モデルを変更したいのですが、少なくとも今のところは不可能です。
したがって、fixture.Createを使用してオブジェクトを作成することはオプションではなく、通常、直後にOmitAllPropertiesを呼び出してオブジェクトを作成します。これにより、AFの能力が制限されます。
そのため、私はそれを処理するいくつかのカスタマイズを作成し、循環参照を省略していました(その後、開発者は循環参照があるかどうかを気にせずにオブジェクトを構築する必要があり、With、なしなど)。 しかし、この変更はこのすべてを壊します。
Omitterアプローチで問題を解決できると思いますか? 私はこのクラスを知りませんでした、とにかく絶対にそれを試してみます。
もう一度ありがとう、そしてあなたが私の反省に何かを加えることができると思うならば、私に知らせてください。
Omitterアプローチで問題を解決できると思いますか? 私はこのクラスを知りませんでした、とにかく絶対にそれを試してみます。
カスタマイズを次のように書き直すと、すべてのテストに合格し始めます。
c#
public class DummyCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
// Don't populate the DummyObject.CircularRef property.
fixture.Customizations.Add(
new Omitter(
new EqualRequestSpecification(
typeof(DummyObject).GetProperty(nameof(DummyObject.CircularRef)))));
}
}
したがって、うん、それはあなたの問題を修正するはずです😉また、このアプローチはあまり面倒に見えないので、受け入れられるはずです。
ご不明な点がございましたら、お気軽にお問い合わせください。
これは完全に機能します。 どうもありがとう! 私はあなたがこれを閉じることができると思います:)
@ Dev-I-Ant素晴らしい、フィードバックをありがとう! :)
最も参考になるコメント
カスタマイズを次のように書き直すと、すべてのテストに合格し始めます。
c# public class DummyCustomization : ICustomization { public void Customize(IFixture fixture) { // Don't populate the DummyObject.CircularRef property. fixture.Customizations.Add( new Omitter( new EqualRequestSpecification( typeof(DummyObject).GetProperty(nameof(DummyObject.CircularRef))))); } }
したがって、うん、それはあなたの問題を修正するはずです😉また、このアプローチはあまり面倒に見えないので、受け入れられるはずです。
ご不明な点がございましたら、お気軽にお問い合わせください。