次のテストはAutoFixtureで成功3.51.0
が、中に失敗する4.0.0-rc1
:
(マスターでの最新のコミットでも: c856cd6
)
`` `c#
[事実]
public void ShouldApplyCustomizationsFromBaseClass()
{{
varfixture = new Fixture();
フィクスチャ。カスタマイズ
var res = fixture.Create
Assert.Equal(0、res.Id);
}
[事実]
public void ShouldApplyCustomizationsFromInterface()
{{
varfixture = new Fixture();
フィクスチャ。カスタマイズ
var res = fixture.Create
Assert.Equal(0、res.Id);
}
パブリックインターフェイスIInterface
{{
int Id {get; 設定; }
}
パブリッククラスBaseClass
{{
public int Id {get; 設定; }
}
パブリッククラスImplClass:BaseClass、IInterface
{{
}
`` `
質問をしてくれてありがとう。 さて、これは望ましい変更であり、意図的に適用されています。
以前は、あるサブタイプのカスタマイズが他のサブタイプに影響を与える可能性があるという問題がありました。 例えば:
`` `c#
class Base {public string Common {get; 設定; }}
クラスChild1:ベース{}
クラスChild2:ベース{}
[事実]
public voidEnsureCustomizationAreNotAffected()
{{
varfixture = new Fixture();
フィクスチャ。カスタマイズ
var result = fixture.Create<Child2>();
Assert.NotNull(result.Common);
}
In the v3 this test failed, causing a lot of confusion to people. As you might imagine, the scenarios were more complicated and it was very non-obvious why the particular members are not initialized.
For instance, the following code will not work, which again proves that API is not designed for that.
```c#
fixture.Customize<Base>(c => c.With(x => x.Common, "foo"));
そのため、この問題を修正するためにないようにしました。 そのPRでわかるように、それは多くのユーザビリティの問題を修正し、より明確になりました(変更は実際に壊れていますが)。
それでもベース/インターフェースのプロパティを省略したい場合は、次のスニペットを使用できます。
`` `c#
プライベートクラスSamePropertySpecification:IRequestSpecification
{{
プライベート読み取り専用タイプ_declaringType;
プライベート読み取り専用文字列_name;
public SamePropertySpecification(Type declaringType, string name)
{
_declaringType = declaringType;
_name = name;
}
public bool IsSatisfiedBy(object request)
{
if (request is PropertyInfo pi)
{
return pi.DeclaringType == this._declaringType &&
pi.Name.Equals(this._name, StringComparison.Ordinal);
}
return false;
}
}
[事実]
public void TestBasePropertyOmitting()
{{
varfixture = new Fixture();
fixture.Customizations.Add(new Omitter(new SamePropertySpecification(typeof(Base), nameof(Base.Common))));
var result = fixture.Create<Child1>();
Assert.Null(result.Common);
}
`` `
その機能が頻繁に必要な場合は、 fixture
独自の拡張メソッドを作成できます。 ただし、非常に紛らわしいように見えるため、このような機能をすぐに使用できないようにすることに投票します。
わかりました、それが意図的だったことを知って良かったです。 紛らわしいことには間違いなく同意しますが、明示的に適用できるのであれば、それは素晴らしい機能です。 スニペットを試します(おそらく拡張メソッドを作成します)。
ちなみに、これは重大な変更リストに追加したいものですか? 同じ質問が投げかけられるのを防ぐかもしれません。
すべてのカスタマイズのいずれか1つのカスタマイズについて、古い動作にオプトインする方法はありませんよね?
これは、重大な変更リストに追加したいものですか?
まあ、それはバグ修正のセクションで言及されています。 以前の動作が「機能」として記述されていなかったため、これは実際には重大な変更ではありません。 むしろ、それは望ましくない副作用であり、最終的に排除されました😉
すべてのカスタマイズのいずれか1つのカスタマイズについて、古い動作にオプトインする方法はありませんよね?
いいえ、アプローチを完全に作り直したので、私が信じるような方法はありません。
スニペットをテストしてください。問題が解決する場合は、お気軽に問題を解決してください。 または、さらに質問がある場合はお知らせください😃
インターフェイスでも機能するように調整し、 'Fixture.Customizeで使用できるように拡張メソッドを作成しました
@nphmuller申し訳ありませんが、私はあなたのきちんと整頓されたコードを壊しました、そして今あなたは生き残る必要があります😄しかしあなたの犠牲は私たち全員のためになされたと信じています、それであなたは私たちをあまり非難しないでしょう😅
責任は一切ありません。 あなたの推論を完全に理解し、同意さえします。 ただ私のために吸う😉
後で問題に飛び込んで、より適切な方法があることを確認するかもしれません。 今のところは大丈夫です。
好奇心から-そのための実際のユースケースは何ですか? そのような機能のニーズを満たしたことがなかったので..通常、テストを作成するときは、ベースタイプやインターフェイスタイプを構成するのではなく、特定のタイプのみをカスタマイズする必要があります。 ある種のグローバルなカスタマイズを書いていますか?
この場合、EntityFramework統合テストのテストデータジェネレーターとしてAutoFixtureを使用します。
エンティティが使用する、共通のプロパティを含むいくつかの基本タイプまたはインターフェースがあります。 Id、tenant-id(およびナビゲーションプロパティ)、そのようなもの。
たとえば、これらのプロパティの1つは、どのユーザーがオブジェクトを作成したかです。 このプロパティはほとんどのテストにとってそれほど興味深いものではなく、生成された場合、生成してデータベースに挿入する必要がある巨大なグラフ(Userクラスにも多くのナビゲーションプロパティがあります)が作成されます。 これにより、オブジェクトがそのように挿入されることを意図していないため、テストが遅くなるか、dbレベルで失敗することさえあります。
したがって、これらのプロパティを単純に除外し、必要に応じてオプトインする方が簡単です。 基本クラスレベルでは、それ以外の場合は、すべてのエンティティタイプに対して同じ省略ルールを作成する必要があるためです。
@nphmuller説明してくれてありがとう、今は明らかです😉うん、シナリオは理にかなっているように見えますが、あなたが必要とすることはめったにないように見えることを認めなければなりません。