はじめに
internalクラスに対してテストコードを書こうとした場合、アクセス制限に引っかかりテストコードが書けない。
この記事ではその場合の解決方法をまとめる。
現象
あるプロジェクトで以下のようなコードがあったとしよう。
Calculatorというクラスに2つの値を渡し、足し算した結果を表示するプログラムだ。
namespace InternalClassSample
{
class Program
{
static void Main(string[] args)
{
var calculator = new Calculator(1, 2);
Console.WriteLine(calculator.DoAddition());
}
}
}
namespace InternalClassSample
{
internal class Calculator
{
private readonly int _left;
private readonly int _right;
public Calculator(int left, int right)
{
_left = left;
_right = right;
}
public int DoAddition()
{
return _left + _right;
}
}
}
どうやらこのCalculatorクラスは同一アセンブリ内でしか使用されていないため、internalクラスとして定義されているようだ。
さて、このたびプロジェクトでは品質を上げるためにテストコードを書くことになったとしよう。
早速、Calculatorクラスに対してテストコードを書くため、テストプロジェクトを用意してテストコードを書いてみた。
namespace InternalClassSample.UnitTest
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Test_DoAddition()
{
var calculator = new InternalClassSample.Calculator(1, 2);
Assert.AreEqual(3, calculator.DoAddition());
}
}
}
早速コンパイルしてテストを走らせてみよう。
error CS0122: 'Calculator' はアクセスできない保護レベルになっています
残念なことにエラーになってしまった。
Calculatorクラスがinternalであるために、新しく追加したテストプロジェクトからはアクセス制限に引っかかってしまうのである。
プロジェクトの方針としてテストコードを書かなければならないが、このままではテストコードを書けない。
このエラーを何とかして回避する方法はないだろうか?
解決方法
私がこの記事で伝える解決方法は以下の2つだ。
1. アクセス制限を緩める
2. 特定のアセンブリにだけinternalクラスを公開する
それぞれについて詳しく解説していこう。
アクセス制限を緩める
こちらの方法はかなり単純な方法だ。
Calclatorクラスのアクセス修飾子がinternalだから見えないのだから、よりアクセス制限が緩いpublicに変更し、テストコードのプロジェクトからも見えるようにすれば良い。
具体的には、コードを以下のように変更する。
// アクセス修飾子をinternalからpublicへ変更する
public class Calculator
この方法のメリットはinternalからpublicへ変えるだけなので、修正が簡単であることだ。
ただし、デメリットとして今後はどこからでも利用可能となるため、使用するべきではないところから呼び出されてしまう可能性が出てくる。
特にコードが膨大になっている場合、アクセス制限を緩めてしまうと、今後、様々な場所から呼び出されてしまい、変更が困難になる可能性もある。
特定のアセンブリにだけinternalクラスを公開する
こちらの方法は先程のデメリットを抑えつつ、修正もそれほど多くないためオススメの方法だ。
InternalsVisibleToAttributeを使い、テストプロジェクトにだけinternalクラスを公開すれば良い。
具体的にはCalculatorクラスが含まれるプロジェクトのAssemblyInfo.csに以下のコードを追記する。
[assembly: InternalsVisibleTo("InternalClassSample.UnitTest")]
こうすることでテストプロジェクトにだけinternalクラスが見えるようになるため、アクセス制限を緩めたりせずにテストコードを書くことができる。
また、上記の1行を追加すれば良いだけなので、修正もそれほど多くならないはずだ。
まとめ
今回はinternalクラスに対してテストコードを書く方法ということで、その方法をまとめてみた。
この記事を書くにあたってInternalsVisibleToAttributeを初めて知ったが、今後テストコードを書く際に使えそうな機能なので覚えておきたいと思う。
それではまた。
TomoProg