web-dev-qa-db-ja.com

ユニットテストを行うときのC#「内部」アクセス修飾子

私はユニットテストに慣れていないので、「内部」アクセス修飾子をもっと使い始めるべきかどうかを考えています。 'internal'を使用してAssembly変数 'InternalsVisibleTo'を設定すると、テストプロジェクトからpublicを宣言したくない関数をテストできることを知っています。これにより、少なくとも各プロジェクトには独自のテストプロジェクトがあるので、常に「内部」を使用する必要があると思います。こんなことをしてはいけない理由を教えてもらえますか? 「プライベート」はいつ使用する必要がありますか?

382
Hertanto Lie

内部クラスをテストする必要があり、assemby属性があります。

using System.Runtime.CompilerServices;

[Assembly:InternalsVisibleTo("MyTests")]

これをプロジェクト情報ファイルに追加します。 Properties\AssemblyInfo.cs

1061
EricSchaefer

プライベートメソッドをテストする場合は、Microsoft.VisualStudio.TestTools.UnitTesting名前空間のPrivateObjectおよびPrivateTypeを見てください。必要なリフレクションコードの周りに使いやすいラッパーを提供します。

ドキュメント: PrivateTypePrivateObject

113
Brian Rasmussen

プライベートも使用でき、リフレクションを使用してプライベートメソッドを呼び出すことができます。 Visual Studio Team Suiteを使用している場合、プライベートメソッドを呼び出すためのプロキシを生成する素晴らしい機能がいくつかあります。プライベートメソッドと保護されたメソッドの単体テストを自分で行う方法を示すコードプロジェクトの記事を次に示します。

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

どのアクセス修飾子を使用すべきかという点で、私の一般的な経験則はプライベートから始め、必要に応じてエスカレートします。そうすれば、クラスの内部の詳細を本当に必要なだけ公開することができ、実装の詳細を必要に応じて非表示に保つことができます。

10
Steven Behnke

デフォルトではプライベートを使用し続けます。メンバーがその型を超えて公開されるべきではない場合、同じプロジェクト内であっても、その型を超えて公開されるべきではありません。これにより、物事がより安全で整頓された状態に保たれます。オブジェクトを使用しているとき、どのメソッドを使用できるかが明確になります。

そうは言っても、自然にプライベートなメソッドをテストの目的で内部に作成することは合理的だと思います。リファクタリングに不向きなリフレクションを使用することを好みます。

考慮すべきことの1つは、「ForTest」サフィックスです。

internal void DoThisForTest(string name)
{
    DoThis(name);
}

private void DoThis(string name)
{
    // Real implementation
}

次に、同じプロジェクト内でクラスを使用している場合、このメソッドを実際に使用するべきではないことは明らかです(現在および将来)。テスト目的でのみ使用します。これは少しハッキーであり、私が自分でやることではありませんが、少なくとも検討する価値があります。

10
Jon Skeet

Ericの答えに加えて、これをcsprojファイルで構成することもできます。

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
      <_Parameter1>MyTests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

または、テストするプロジェクトごとに1つのテストプロジェクトがある場合は、Directory.Build.propsファイルで次のようなことができます。

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

参照: https://stackoverflow.com/a/49978185/167805

1
gldraphael