MS Test でプライベート メソッドを単体テストする方法
始める前に、MS Testを使用してプライベートメソッドをユニットテストする方法を説明します。プライベートメソッドをテストするのが良い考えかどうかについて話し合いましょう。
私はしばしば、2つの考え方があることを見てきました。
- プライベートメソッドはテストする必要があります。
- プライベートメソッドはテストしないでください。
これらのことを大局的に見るために、次のリストに示すように、テスト対象システム (SUT) の給与クラスについて考えてみましょう。
namespace Calculator
{
public class Salary
{
public int CalculateSal(int bs, int nwd)
{
int ts ;
if(isValidNwd(nwd))
{
ts= bs*nwd;
}
else
{
ts = 1000;
}
return ts;
}
private bool isValidNwd(int nwd)
{
if (nwd > 8)
{
return true;
}
else
{
return false;
}
}
}
}
テスト対象のシステム Salary クラスには、次の 2 つの機能があります。
- CalculateSal メソッドは公開メソッドであり、給与を計算するために 2 つのパラメーターを取ります
- isValidwd メソッドはプライベートメソッドで、1 つのパラメータを取ります。この関数は、稼働日数が 8 を超える場合は true を返し、それ以外の場合は false を返します。
- CalculateSal メソッドは、まず、プライベート メソッド isValidWd を使用して、稼働日数が有効かどうかを確認します。
- 就業日数が有効な場合、給与は基本給と就業日数を掛けて計算されるか、それ以外の場合は1000ドルに固定されます。
これで、2つの関数を持つテスト対象のシステムSalaryクラスができました。

1つの意見は、プライベートメソッドを個別にユニットテストすべきではないというものです。これは、プライベートメソッドがパブリックメソッド内で使用され、パブリックメソッドの動作をテストすると、プライベートメソッドの動作もテストされるためです。
別の意見は、プライベートメソッドは、他のパブリックメソッドまたはプライベートメソッドと分離して、それ自体の動作についてユニットテストする必要があるというものです。プライベートメソッドのテスト方法を確認する前に、これを回避する別の可能な方法があるかどうかを考えてみましょう。
Violating Single Responsibility Principle
現在、テスト対象の給与クラスは、次の 2 つの責任があるため、単一責任原則に違反しています。
- 給与を計算するため(公開方式)
- 稼働日数を検証するには (private メソッド)

SUT Salaryクラスのコードカバレッジが良好であるかどうかは、クラスの就業日の検証動作をテストしない限り、またプライベート設計では確認できません。良いオプションはこれかもしれません: Salary クラスを作成するときに、公開メソッドを使用して 2 つの別々のクラスに責任をこぼし、給与を計算し、稼働日を検証できます。その後、両方のクラスのパブリックメソッドのユニットテストを記述できます。それを行う方法を見てみましょう。
プライベートメソッドのユニットテストの記述
SUT クラスのプライベート メソッドをテストする必要があるという意見がある場合は、次の 2 つのオプションがあります。
- リファクタリングを使用しますが、これは少し複雑です。
- VSTS PrivateObjectクラスを使用する - これは簡単です!

PrivateObjectクラスを使用してプライベートメソッドをユニットテストする方法を見てみましょう。プライベートオブジェクトクラスを使用するには、次のことを行う必要があります。
- テスト プロジェクトにMicrosoft.VisualStudio.QualityTools.UnitTestFrameworkの参照を追加します。単体テストプロジェクトのテンプルを選択してプロジェクトを作成した場合、この参照はデフォルトでプロジェクトに追加されます。
- Add a namespace Microsoft.VisualStudio.TestTools.UnitTesting.
PrivateObjectClass のコンストラクタは、型をパラメータとして受け取るため、ここではSUT Salary クラスの型を渡し、PrivateObjectClass のオブジェクトでinvokeメソッドを呼び出してプライベート メソッドを呼び出す必要があります。
以下のリストに示すように、プライベートメソッドisValidNwdをテストできます。
[TestMethod]
public void ReturnTrueForValidWorkingDays() {
PrivateObject objToTestPrivateMethod=new PrivateObject(typeof(Salary));
bool result=Convert.ToBoolean(objToTestPrivateMethod.Invoke("isValidNwd", 6));
Assert.AreEqual(result, true);
}
基本的に、私たちは次のタスクを実行しています。
・ PrivateObjectクラスのオブジェクトの作成
・ Salary クラスの型をコンストラクタの入力パラメータとして渡す
・ invokeメソッドを使用してSUT Salaryクラスのprivateメソッドを実行する
・ invokeメソッドで2つのパラメータを渡す:最初のパラメータはプライベートメソッドの名前で、2番目のパラメータは実行中にプライベートメソッドに渡される引数です
そして、それがプライベートメソッドのユニットテストを行う方法です!
結論
この投稿では、次のことを学びました。
- プライベートメソッドをテストするかどうか
- PrivateObjectクラスを使用してプライベートメソッドをテストする方法
この投稿がお役に立てば幸いです–読んでくれてありがとう。ハッピーコーディング!
