System.Reflection経由で内部メンバーにアクセスしますか?
-
05-07-2019 - |
質問
多くの内部関数を持つクラスを単体テストしようとしています。これらも明らかにテストが必要ですが、私のTestsプロジェクトは、主に多くの小さな関連プロジェクトをカバーしているため、分離しています。私がこれまでに持っているものは:
FieldInfo[] _fields =
typeof(ButtonedForm.TitleButton).GetFields(
BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.DeclaredOnly);
Console.WriteLine("{0} fields:", _fields.Length);
foreach (FieldInfo fi in _fields)
{
Console.WriteLine(fi.Name);
}
これにより、すべてのプライベートメンバーが適切に吐き出されますが、内部は表示されません。 Visual Studioが生成できる自動生成されたテストをいじっていたときに、Testプロジェクトの内部の表示に関係することを尋ねられたため、これが可能であることを知っています。さて、今私はNUnitを使用していて本当に気に入っていますが、どうすれば同じことを実現できますか?
解決
InternalsVisibleTo
属性を使用して、ユニットテストアセンブリにアセンブリの内部メンバーへのアクセスを許可します。
ここにいくつかの役立つ追加情報とウォークスルーのリンクがあります:
実際に質問に答えるには... .NET Reflection APIでは、内部および保護は認識されません。 MSDN からの引用:
ILで保護されているC#キーワードおよびinternalは意味がなく、Reflection APIでは使用されません。 ILの対応する用語は、FamilyおよびAssemblyです。 Reflectionを使用して内部メソッドを識別するには、 IsAssembly を使用しますa>プロパティ。保護された内部メソッドを識別するには、 IsFamilyOrAssembly 。
他のヒント
InternalsVisibleTo アセンブリレベル属性の追加メインプロジェクトに、テストプロジェクトのアセンブリ名を指定すると、内部メンバーが表示されるはずです。
たとえば、クラス外のアセンブリに次を追加します。
[assembly: InternalsVisibleTo("AssemblyB")]
またはより具体的なターゲティングの場合:
[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")]
アプリケーションアセンブリに厳密な名前がある場合、テストアセンブリにも厳密な名前を付ける必要があります。
プライベートメソッドの単体テストを作成するかどうかを尋ねる必要があると思いますか? 「合理的な」コードカバレッジでパブリックメソッドの単体テストを作成する場合、結果として呼び出す必要があるプライベートメソッドを既にテストしていませんか?
テストをプライベートメソッドに結び付けると、テストはより脆弱になります。テストを中断することなく、プライベートメソッドの実装を変更できるはずです。
参照:
http://weblogs.asp.net/tgraham/ archive / 2003/12/31 / 46984.aspx http://richardsbraindump.blogspot.com/2008 /08/should-i-unit-test-private-methods.html http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 http://geekswithblogs.net/geekusconlivus/archive/2006/07/13 /85088.aspx
コードはフィールドのみを表示しています-フィールドは常にプライベートIMOである必要があるため、内部メンバーが表示されないことを願っています。 (定数の潜在的な例外を除きます。)
ButtonedForm.TitleButtonには実際には非プライベートフィールドがありますか?内部のメソッドを見つけようとしている場合は、明らかに GetMethods
(または GetMembers
)を呼び出して取得する必要があります。
他の人が示唆しているように、 InternalsVisibleTo
はテストに非常に便利です(ほとんどテストにのみ!)。内部メソッドをテストする必要があるかどうかについては、そうすることができると確かに便利だと思います。ユニットテストは、排他的にブラックボックステストであるとは考えていません。多くの場合、簡単な方法で接続されたいくつかの内部メソッドを使用してパブリック機能が実装されていることを知っている場合、各内部メソッドといくつかの「擬似統合」の徹底的なテストを簡単に実行できます。パブリックメソッドでテストします。
InternalsVisibleを使用する理由は、私の状況下です。チャートコントロールのソースコードを購入します。そのソース管理に変更を加え、独自のバージョンをコンパイルする必要がある場所を見つけました。これで何も破られなかったことを確認するために、いくつかの内部フィールドへのアクセスを必要とするユニットテストを作成する必要があります。
これは、InternalsVisibleが理にかなっている完璧なケースです。
しかし、ソースにアクセスできない場合はどうしますか?どのようにして内部フィールドに到達できますか? .Net Reflectorはそのコードを見ることができますが、ILを見ているだけだと思います。