VS2017 .Net標準ライブラリの内部メソッドの単体テスト


150

現在、.Net Standard 1.6ライブラリを作成して、最新のVisual Studio 2017リリース候補版を試しています。私はコードの単体テストにxUnitを使用しており、VS2017で内部メソッドを引き続きテストできるかどうか疑問に思っていました。

指定したプロジェクトが内部メソッドを表示できるようにするVS2015のすべての行AssemblyInfo.csクラスを使用できることを覚えています

[assembly:InternalsVisibleTo("MyTests")]

VS2017 .Net StandardプロジェクトにはAssemblyInfo.csクラスがないため、内部メソッドを単体テストできるかどうか疑問に思いましたか?


3
あなたは、必要があるだけでは外部に見える機能からユニットテスト、コードのことができるように。結局のところ、外部コードからの論理パスがこれらの内部メソッドに到達できない場合、そもそも何をしているのでしょうか。
デビッド

3
@David私はこれを行うことができますが、以前はいくつかの内部クラスの周りに単純な単体テストを配置しました。テストでより明確にするために。
Phil Murray

5
私の知る限り、あなたはこの属性をnamespaceブロックの外にある他のファイルに置くことができ、コンパイルする必要があります。魔法のようなことはありませんAssemblyInfo.cs。うまくいきませんか?もちろん、正しいusing句を追加するか、完全修飾属性を使用する必要があります[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")]
Groo

1
@デビッドあなたが内部クラスとライブラリを作成しているし、あなたがテストする必要があり、これらのクラスを模擬した場合、InternalsVisibleTo重大である-例えば、ここで- stackoverflow.com/a/17574183/43453
PandaWood

回答:


210

.NETドキュメントにInternalsVisibleToAttributeよると:

属性はアセンブリレベルで適用されます。つまり、ソースコードファイルの先頭に含めることも、Visual StudioプロジェクトのAssemblyInfoファイルに含めることもできます。

つまり、任意の名前の.csファイルに配置するだけで、問題なく動作するはずです。

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]

1
@PhilMurray:また、ここでAssemblyInfo.cs説明するような「クラシック」ファイルを作成できるようにする設定があるようです。それ以外の場合は、「説明」、「著作権」などのすべての属性が.csprojファイル内に保存されます。
Groo

43

ここで説明するように:

https://blog.sanderaernouts.com/make-internals-visible-with-new-csproj-format

別のItemGroupを追加することにより、プロジェクトファイル内に内部の可視属性を追加することが可能です:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(AssemblyName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

あるいは:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

プロジェクトファイルがそのような懸念を定義するのに適切な場所であると思われるので、私はそのソリューションが好きです。


8

最初の答えはまったく問題ありませんが。オリジナルでこれを実行したいAssemblyInfo場合は、常にファイルを自動生成せずに手動で追加することを選択できます。

<PropertyGroup>
   <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

詳細:https : //stackoverflow.com/a/47075759/869033


5

"InternalsVisibleTo"属性は、.Netをテストするあらゆる種類の "ホワイトボックス"(おそらく10年という言葉)のテストの鍵となります。前面に「assembly」属性がある任意のc#ファイルに配置できます。MS DOCは、アセンブリ名が署名されている場合、公開鍵トークンで修飾する必要があると述べていることに注意してください。うまくいかないことがあり、代わりに完全な公開鍵を使用する必要があります。内部へのアクセスは、並行システムのテストや他の多くの状況で重要です。https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054を参照してください。この本では、Meszarosがプログラム開発への「テストのための設計」アプローチを基本的に構成するさまざまなコーディングスタイルについて説明しています。少なくともそれは私が長年使ってきた方法です。

追加:すみません、しばらくここにいません。Meszarosでは、1つのアプローチを「テストサブクラス」アプローチと呼んでいます。繰り返しになりますが、基本クラスの内部にアクセスするには、「internalsvisableto」を使用する必要があります。これは優れたソリューションですが、密封されたクラスでは機能しません。私が「Design For Test」を教えるとき、それはテスト可能性を提供するために基本クラスに「事前設計」されることが要求されるものの1つであることを提案します。それはほとんど文化的なものにならなければなりません。封印されていない「基本」基本クラスを設計します。UnsealedBaseClassまたはそれと同じように認識できる名前を付けます。これは、テストのためにサブクラス化されるクラスです。また、プロダクション用の封印されたクラスを構築するためにサブクラス化され、公開するコンストラクターのみが異なる場合がよくあります。私は原子力業界で働いており、テスト要件は非常に真剣に受け止められています。だから、私はいつもこれらのことを考えなければなりません。ちなみに、プロダクションコードにテストフックを残すことは、.Net実装の「内部」である限り、この分野の問題とは見なされません。何かをテストしないことによる影響は非常に深刻なものになる可能性があります。


1

もう1つの方法は、ターゲットメソッド内で 'ラッパー' TestMyFooパブリッククラスを使用することです。このクラスには、パブリックメソッドがあり、テストする必要のあるクラス(MyFooなど)から継承します。これらのパブリックメソッドは、テストする基本クラスを呼び出すだけです。

ターゲットプロジェクトでテストフックを出荷することになるため、これは「理想的」ではありません。ただし、最新の信頼性の高い自動車には診断ポートが付属しており、最新の信頼性の高い電子機器にはJTAG接続が付属していることを考慮してください。しかし、診断ポートを使用して車を運転するのに十分な愚か者はいない。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.