Windows 7でC#を使用して.NET 4.0に取り組んでいます。
モックを使用していくつかのメソッド間の通信をテストしたいと思います。唯一の問題は、インターフェイスを実装せずにそれをやりたいということです。それは可能ですか?モックオブジェクトに関する多くのトピックといくつかのチュートリアルを読みましたが、それらはすべてクラスではなく、インターフェイスのモックに使用されていました。 RhinoおよびMoqフレームワークを使用しようとしました。
偽造する必要のあるメソッドをvirtual
(プライベートではない)としてマークするだけです。その後、メソッドをオーバーライドできる偽物を作成できるようになります。
new Mock<Type>
を使用し、パラメータなしのコンストラクタがない場合は、param Objects
の型をとるため、上記の呼び出しの引数としてパラメータを渡すことができます
ほとんどのモックフレームワーク(MoqおよびRhinoMocksを含む)は、モックされたクラスの代わりとしてプロキシクラスを生成し、定義した動作で仮想メソッドをオーバーライドします。このため、インターフェイス、または具象クラスまたは抽象クラスの仮想メソッドのみをモックできます。さらに、具象クラスをモックしている場合、モックフレームワークがクラスをインスタンス化する方法を認識できるように、ほとんどの場合、パラメータなしのコンストラクタを提供する必要があります。
コードにインターフェースを作成することを嫌うのはなぜですか?
MoQを使用すると、具象クラスをモックできます。
var mocked = new Mock<MyConcreteClass>();
ただし、これによりvirtual
コード(メソッドとプロパティ)をオーバーライドできます。
標準のモックフレームワークは、プロキシクラスを作成しています。これが、それらが技術的にインターフェースと仮想メソッドに限定されている理由です。
「通常の」メソッドをモックしたい場合は、プロキシ生成の代わりにインスツルメンテーションで機能するツールが必要です。例えば。 MS MolesとTypemockはそれを行うことができます。しかし、前者には恐ろしい「API」があり、後者は商用です。
そのクラスのインターフェイスを作成する方が良いと思います。インターフェイスを使用して単体テストを作成します。
そのクラスにアクセスできない場合は、そのクラスのアダプターを作成できます。
例えば:
public class RealClass
{
int DoSomething(string input)
{
// real implementation here
}
}
public interface IRealClassAdapter
{
int DoSomething(string input);
}
public class RealClassAdapter : IRealClassAdapter
{
readonly RealClass _realClass;
public RealClassAdapter() => _realClass = new RealClass();
int DoSomething(string input) => _realClass.DoSomething(input);
}
このようにして、IRealClassAdapterを使用してクラスのモックを簡単に作成できます。
それがうまくいくことを願っています。
テスト対象のクラスを変更できない場合、提案できる唯一のオプションは、MS Fakes https://msdn.Microsoft.com/en-us/library/hh549175.aspx を使用することです。ただし、MS FakesはVisual Studioのいくつかのエディションでのみ機能します。
さらに悪化した場合は、インターフェイスとアダプターのペアを作成できます。 ConcreteClassのすべての使用を変更して代わりにインターフェースを使用し、実動コードでは具象クラスの代わりに常にアダプターを渡します。
アダプターはインターフェースを実装するため、モックはインターフェースも実装できます。
メソッドを仮想化したり、インターフェイスを追加したりするだけではなく、具体的なクラスのソースにアクセスできない場合は、バインドから抜け出すことができます。
私が働いていた古いプロジェクトとレガシープロジェクトの1つで、インターフェイスやベストプラクティスが含まれていないものに直面しました。また、プロジェクトビジネスの成熟度のために、物事を再構築したり、コードをリファクタリングすることを強制するのは非常に困難です私のUnitTestプロジェクトでは、モックしたいクラスのラッパーを作成し、そのラッパーは、セットアップして使用したいすべての必要なメソッドを含むインターフェイスを実装していましたが、実際のクラスの代わりにラッパーをモックできます。
例えば:
仮想メソッドを含まないか、インターフェイスを実装しないテストするサービス
public class ServiceA{
public void A(){}
public String B(){}
}
Moqへのラッパー
public class ServiceAWrapper : IServiceAWrapper{
public void A(){}
public String B(){}
}
ラッパーインターフェース
public interface IServiceAWrapper{
void A();
String B();
}
単体テストでは、ラッパーをモックできます。
public void A_Run_ChangeStateOfX()
{
var moq = new Mock<IServiceAWrapper>();
moq.Setup(...);
}
これはベストプラクティスではないかもしれませんが、プロジェクトルールでこのように強制されている場合は実行してください。また、不要なラッパーやアダプターでプロジェクトをオーバーロードしないように、ユニットテスト専用に指定されたユニットテストプロジェクトまたはヘルパープロジェクト内にすべてのラッパーを配置します。
更新:この回答は1年以上でしたが、今年は異なるソリューションで多くの同様のシナリオに直面しました。たとえば、Microsoft Fake Frameworkを使用すると、モック、偽物、スタブを簡単に作成でき、インターフェイスなしでプライベートメソッドや保護されたメソッドをテストすることもできます。読むことができます: https://docs.Microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-Microsoft-fakes?view=vs-2017