Microsoft Moles Isolation Framework、さらに掘り下げ

名前からわかるように、Microsoft Researchの製品-Microsoft Moles Isolation Frameworkについて説明します。 haberraiser alek_sysの 投稿を読んだ後、初めて彼に会いました。 私はがとても好きだったので、その使用の経験を共有することにしました。

なんで?


最初に、Microsoft.Molesが意図する目的と、Microsoft.Molesで何を達成できるかを判断します。


一般的な単体テストについて


上記の目標に疑問がある場合は、単体テストの主要なポイントを思い出して少し更新する価値があります。 疑いのない人-次のセクションにスキップできます。

ユニットテストとは何ですか?
単体テストの要件

単体テストを使用するときに生じる問題

単体テストツールキット。

現時点では、さまざまな目的(ユニットテスト、統合テスト、機能テスト、UIテスト)の自動テストを作成および使用するために設計された多くのプログラミング言語用のフレームワーク(NUnit、JUnit、DUnit、xUnit、MSTest)が多数あります。 原則として、テストされたコードが周囲のロジックから完全に分離されていることを保証できないため、純粋な形式で完全な単体テストを作成することはできません。 開発者は、さまざまなトリックに頼り、追加のモッククラスのクラウドを作成し、リフレクションを使用する必要があります。 そして、ここでIsolation Frameworksが役立ちます。これにより、便利かつ迅速に、単体テスト用の分離された環境を整理できます。MicrosoftMolesもその1つです。

Microsoft.Molesは何ができますか?


モルが私たちに例を提供する可能性を実証しようとします(可能な限り単純にしようとしましたが、その中でモルを使用することを正当化するのに十分なほど難しくしました)。

ローカルファイルハッシュとリモートファイルハッシュが一致しない場合に、リモートストレージからダウンロードしたファイルでローカルストレージのファイルを更新するタスクが唯一のUpdateFileFromService(string fileId)メソッドを持つFileUpdaterクラスがあるとします。
リストからわかるように、UpdateFileFromServiceメソッドはFileManagerクラスとStorageServiceクラスを使用して、ローカルおよびリモートのリポジトリにアクセスします。 FileManagerクラスとStorageServiceクラスのメソッドの実装を意図的に引用することはありません。したがって、それらのインターフェイスを知るだけで済みます。

public class FileUpdater
{
private StorageService storageService;

public StorageService Service
{
get
{
if (storageService == null )
{
storageService = new StorageService();
}
return storageService;
}
}

public void UpdateFileFromService( string fileId)
{
if ( string .IsNullOrEmpty(fileId))
{
throw new Exception( "fileId is empty" );
}
var fileManager = new FileManager();
string localFileHash = fileManager.GetFileHash(fileId);
string remoteFileHash = Service.GetFileHash(fileId);
if (localFileHash != remoteFileHash)
{
FileStream file = Service.DownloadFile(fileId);
fileManager.SaveFile(fileId, remoteFileHash, file);
}
}
}

public class FileManager
{
public string GetFileHash( string fileId)
{
throw new NotImplementedException();
}

public void SaveFile( string fileId, string remoteFileHash, FileStream file)
{
throw new NotImplementedException();
}
}

public class StorageService
{
public string GetFileHash( string fileId)
{
throw new NotImplementedException();
}

public FileStream DownloadFile( string fileId)
{
throw new NotImplementedException();
}
}


* This source code was highlighted with Source Code Highlighter .


UpdateFileFromServiceメソッドの次のバージョンは明らかです。
  1. fileId-空の文字列
  2. ローカルとリモートのファイルハッシュは同一ではありません
  3. ローカルとリモートのファイルハッシュは同一です
FileUpdaterクラスのこの実装には処理が含まれていないため、残りの状況は考慮しません。
最初のケースのテスト実装は、テストフレームワークの標準ツールを使用した初歩的なものであるため、Microsoft.Molesを使用してオプション2および3のテストを作成してみましょう。

ほくろおよびスタブクラスの生成

まず、クラスを含むライブラリのMoledアセンブリを生成する必要があります。クラスのロジックは、カスタムデリゲート(それ以外の場合はスタブメソッド)に置き換えます。 これは、Mole.exeを使用したコマンドラインを使用して実行できます。mole.exeは、Microsoft.Molesのインストールパッケージに含まれており、Visual Studio 2008/2010インターフェイスからも使用できます。 2番目の方法を使用します。
ご覧のとおり、Microsoft.Molesをインストールすると、参照アセンブリ用の新しいコンテキストメニュー項目「Add Moles Assembly」が表示されました(図1)。



ClassLibrary1アセンブリでこのコマンドを実行すると、 ClassLibrary1.molesファイルの新しいグループが取得されます(図2)。そこからClassLibrary1.molesファイルはMoledアセンブリ記述子であり、生成用のパラメーターを含み、必要に応じて変更できます。 残りのファイルは各ビルドで自動的に再生成され、編集する意味はありません。



Microsoft.Molesでは、2つのタイプの代替クラスを使用できます-スタブ&モール。
個人的には、両方のオプションが同じように便利であることが判明し、使用に支障はありませんでした。
生成されたアセンブリClassLibrary1.Moles.dllには、デフォルトで、アセンブリClassLibrary1.dllに含まれる各クラスのクラスのペアM%ClassName%とS%ClassName%が含まれています。
ここで:

必要に応じて、 ClassLibrary1.molesファイルに変更を加えることで、特定のクラスに対してのみMolesまたはStubが生成されるようにし(生成時間を大幅に短縮します)、MoleまたはStubを使用していない場合は生成を無効にしたり、その他を設定したりできます生成パラメータ(インテリジェンスは、有効なパラメータとその目的のリストを教えてくれます)。 moles.exeコマンドラインを使用して生成するときにClassLibrary1.moles ファイルを使用することもできます(moles.exeパラメーターのリストは、パラメーターなしでmoles.exeを実行することで確認できます)。

Moleクラスを使用する

MolesとStubsの使用はやや似ているため、この記事ではMicrosoft.Molesのすべての機能について完全に説明するふりをしていません。Moleの使用例のみを取り上げます。
例をより明確にするために、生成されたMoleおよびStubクラスのメンバーの命名機能にすぐに注意します。最初に元のクラスのメンバーの名前が来て、次に渡されたパラメーターの型名がそれに追加されます。 たとえば、 MFileManager.AllInstances.GetFileHashString、FileManager.GetFileHash(string fileId)メソッドをオーバーライドするプロパティです。 このスタイルは、オーバーロードされたメソッドに対して生成されたメンバーの一意性を確保する必要性に関連していると思います。
Moleを使用すると、クラスのメソッドとプロパティをさまざまな方法で置き換えることができます。

明らかに、ラムダ式では、着信値のあらゆる種類のアサートチェックを実行したり、
所定の結果が返ってくる俊敏性。

InstanceBehavior

また、代わりのデリゲートを明示的に指定していないクラスメンバーの動作を指定する可能性も注目に値します。 Moleが生成した各クラスにはInstanceBehaviorプロパティがあり、次の値を取ることができます

テスト実装例

これは、ローカルファイルとリモートファイルのハッシュが異なる場合の状況の実際のテストです。
///
/// ,
///
[TestMethod]
[HostType( "Moles" )]
public void TestUpdateFileNonMatchedHash()
{
var callOrder = 0; //
var testFileId = Guid .NewGuid().ToString();
var testLocalHash = Guid .NewGuid().ToString();
var testRemoteHash = Guid .NewGuid().ToString();
var testFileStream = new FileStream ( @"c:\testfile.txt" , FileMode .OpenOrCreate);

var storageServiceMole = new MStorageService() { InstanceBehavior = MoleBehaviors.Fallthrough };
// GetFileHash StorageService
storageServiceMole.GetFileHashString = (fileId) =>
{
Assert.AreEqual(1, callOrder++); //
Assert.AreEqual(testFileId, fileId);
Assert.AreNotEqual(testLocalHash, testRemoteHash);
return testRemoteHash;
};
storageServiceMole.DownloadFileString = (fileId) =>
{
Assert.AreEqual(2, callOrder++);
Assert.AreEqual(testFileId, fileId);
return testFileStream;
};
// FileManager.
//MFileManager.AllInstances FileManager UpdateFile
// ,
// FileManager
MFileManager.AllInstances.GetFileHashString = (fileManager, fileId) =>
{
Assert.AreEqual(0, callOrder++);
Assert.AreEqual(testFileId, fileId);
return Guid .NewGuid().ToString();
};
MFileManager.AllInstances.SaveFileStringStringFileStream = (fileManager, fileId, fileHash, fileStream) =>
{
Assert.AreEqual(3, callOrder++);
Assert.AreEqual(testFileId, fileId);
Assert.AreEqual(testRemoteHash, fileHash);
Assert.AreSame(testFileStream, fileStream);
};
var fileUpdaterMole = new MFileUpdater
{
InstanceBehavior = MoleBehaviors.Fallthrough,
// getter FileUpdater.Service , moled StorageService
ServiceGet = () => storageServiceMole.Instance
};
var fileUpdater = fileUpdaterMole.Instance;

fileUpdater.UpdateFileFromService(testFileId);
}


* This source code was highlighted with Source Code Highlighter .


2番目の状況-ハッシュが同一の場合、テストを自分で実装してみてください。

追加情報



とりあえずこれを終了します。この情報がおもしろければ継続するかもしれません。

ソース


Microsoft Molesリファレンスマニュアル
NUnit、NAnt、および.NET 3.5でMS Molesを使用する
MSDN-モレフレームワーク

Source: https://habr.com/ru/post/J101408/


All Articles