コードを内部に作成しますが、他のプロジェクトから単体テストに使用できるようにします
-
01-07-2019 - |
質問
すべての単体テストを独自のプロジェクトに入れます。単体テストのためだけに特定のクラスを内部ではなく公開する必要があることがわかりました。とにかくこれを行わなくて済むようにする方法はありますか。クラスをシールドではなくパブリックにすることによるメモリへの影響は何ですか?
解決
.NET を使用している場合は、 内部の可視先 Assembly 属性を使用すると、「フレンド」アセンブリを作成できます。これらは、内部クラスおよび他のアセンブリのメンバーへのアクセスを許可される、特定の厳密な名前が付けられたアセンブリです。
これは、関連するアセンブリを緊密に結合するため、慎重に使用する必要があることに注意してください。InternalsVisibleTo の一般的な用途は、単体テスト プロジェクトです。上記の理由により、実際のアプリケーション アセンブリで使用するのはおそらく適切な選択ではありません。
例:
[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{
他のヒント
内部クラスの場合は、単独で使用してはいけません。したがって、そのオブジェクトを内部で使用する他のクラスのテストとは別に、実際にテストするべきではありません。
クラスのプライベート メンバーをテストすべきでないのと同様に、DLL の内部クラスをテストすべきではありません。これらのクラスは、公的にアクセス可能なクラスの実装の詳細であるため、他の単体テストを通じて十分に演習する必要があります。
内部実装の詳細をテストするとテストが脆弱になるため、クラスの動作のみをテストしたいという考えです。すべてのテストを中断することなく、クラスの実装の詳細を変更できる必要があります。
そのクラスを本当にテストする必要があることがわかった場合は、そもそもなぜそのクラスが内部クラスであるのかを再検討することをお勧めします。
文書化目的のため
あるいは、次を使用して内部クラスをインスタンス化することもできます Type.GetType
方法
例
//IServiceWrapper is public class which is
//the same assembly with the internal class
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
.CreateInstance(type, new object[1] { /*constructor parameter*/ });
ジェネリック型の場合は、次のような異なるプロセスがあります。
var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
.CreateInstance(genType, new object[1] { /*constructor parameter*/});
クラスはパブリックにもシールにもできます。
でも、そんなことはしないでください。
内部クラスをリフレクションするツールを作成し、リフレクション経由ですべてにアクセスする新しいクラスを発行できます。MSTest がそれを行います。
編集:つまり、元のアセンブリに「いかなる」テスト要素も含めたくない場合です。これは、メンバーが非公開の場合にも機能します。