このシリーズも残り僅か。今回もよろしくお願いします。Typemock は、Isolator の Quick Start で、MessageBox をモックに入れ替えるサンプルを紹介しています。これも Prig(と Moq)に移行することが可能です。
以下の記事、ライブラリを使用/参考にさせていただいています。この場を借りてお礼申し上げます m(_ _)m
Testing code that rely on Microsoft Azure Management Libraries using Microsoft Fakes
c# - The type is defined in an assembly that is not referenced, how to find the cause - Stack Overflow
.net - Mircosoft fakes - shims without ShimsContext - Stack Overflow
Unit Test for ShimDataTableCollection Count
c# - How to know if a MemberInfo is an explicit implementation of a property - Stack Overflow
#5816 (any_range requires copyable elements) – Boost C++ Libraries
#10360 (Since 1.56, any_range use static cast of reference instead of implicit conversion) – Boost C++ Libraries
#10493 (Since 1.56, any_range with non-reference references can cause UB) – Boost C++ Libraries
hunting bugs with git bisect and submodules - Least Significant Bit
AdventCalendar - git bisect で問題箇所を特定する - Qiita
便利!電動歯ブラシ | Boost.勉強会 #16 大阪
目次
準備
まずは、間接設定を作成する必要があります。Package Manager Console を開き、Default project: をテストプロジェクトに変更してください。その後、以下のコマンドを実行します:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PM> dir | |
Directory: C:\users\akira\documents\visual studio 2013\Projects\IsolatorMigrationDemo | |
Mode LastWriteTime Length Name | |
---- ------------- ------ ---- | |
d---- 2014/10/10 9:31 IsolatorMigrationDemo | |
d---- 2014/10/10 9:37 IsolatorMigrationDemoTest | |
d---- 2014/10/10 9:37 packages | |
-a--- 2014/10/10 9:32 1561 IsolatorMigrationDemo.sln | |
PM> cd .\IsolatorMigrationDemo\bin\Debug | |
PM> dir | |
Directory: C:\users\akira\documents\visual studio 2013\Projects\IsolatorMigrationDemo\IsolatorMigrationDemo\bin\Debug | |
Mode LastWriteTime Length Name | |
---- ------------- ------ ---- | |
-a--- 2014/10/10 9:31 7680 IsolatorMigrationDemo.exe | |
-a--- 2014/10/10 9:30 189 IsolatorMigrationDemo.exe.config | |
-a--- 2014/10/10 9:31 28160 IsolatorMigrationDemo.pdb | |
-a--- 2014/10/10 9:30 23168 IsolatorMigrationDemo.vshost.exe | |
-a--- 2014/10/10 9:30 189 IsolatorMigrationDemo.vshost.exe.config | |
-a--- 2013/06/18 21:28 490 IsolatorMigrationDemo.vshost.exe.manifest | |
PM> padd -af (dir .\IsolatorMigrationDemo.exe).FullName | |
PM> padd -as "System.Windows.Forms, Version=4.0.0.0" | |
PM> | |
次に、Isolator のサンプルで使用しているメソッドのための間接設定を取得しましょう。PowerShell(コンソール)を開き、情報を取得するために以下のコマンドを実行します:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PS> $pwd | |
Path | |
---- | |
C:\Users\Akira\Documents\Visual Studio 2013\Projects\IsolatorMigrationDemo\IsolatorMigrationDemo\bin\Debug | |
PS> powershell | |
Windows PowerShell | |
Copyright (C) 2013 Microsoft Corporation. All rights reserved. | |
PS> ipmo "C:\Users\Akira\Documents\Visual Studio 2013\Projects\IsolatorMigrationDemo\packages\Prig.1.0.0\tools\Urasandesu.Prig" | |
PS> dir | |
Directory: C:\Users\Akira\Documents\Visual Studio 2013\Projects\IsolatorMigrationDemo\IsolatorMigrationDemo\bin\Debug | |
Mode LastWriteTime Length Name | |
---- ------------- ------ ---- | |
-a--- 2014/10/10 9:31 7680 IsolatorMigrationDemo.exe | |
-a--- 2014/10/10 9:30 189 IsolatorMigrationDemo.exe.config | |
-a--- 2014/10/10 9:31 28160 IsolatorMigrationDemo.pdb | |
-a--- 2014/10/10 9:30 23168 IsolatorMigrationDemo.vshost.exe | |
-a--- 2014/10/10 9:30 189 IsolatorMigrationDemo.vshost.exe.config | |
-a--- 2013/06/18 21:28 490 IsolatorMigrationDemo.vshost.exe.manifest | |
PS> $asmInfo = [System.Reflection.Assembly]::LoadFrom((dir .\IsolatorMigrationDemo.exe).FullName) | |
PS> $asmInfo.GetTypes() | |
IsPublic IsSerial Name BaseType | |
-------- -------- ---- -------- | |
True False Form1 System.Windows.Forms.Form | |
False False Program System.Object | |
True False SomeClass System.Object | |
True False UserOfSomeClass System.Object | |
False False Resources System.Object | |
False False Settings System.Configuration.ApplicationSettingsBase | |
PS> $asmInfo.GetTypes() | ? { $_.Name -match 'Class' } | |
IsPublic IsSerial Name BaseType | |
-------- -------- ---- -------- | |
True False SomeClass System.Object | |
True False UserOfSomeClass System.Object | |
PS> $asmInfo.GetTypes() | ? { $_.Name -match 'Class' } | pfind | |
Method | |
------ | |
Void MyMethod() | |
Void .ctor() | |
Void DoSomething() | |
Void .ctor() | |
PS> $asmInfo.GetTypes() | ? { $_.Name -match 'Class' } | pfind | pget | clip # この結果については、IsolatorMigrationDemo.v4.0.30319.v1.0.0.0.prig に貼り付けてください。 | |
PS> $asmInfo = [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | |
PS> $asmInfo.GetTypes() | ? { $_.Name -eq 'messagebox' } | |
IsPublic IsSerial Name BaseType | |
-------- -------- ---- -------- | |
True False MessageBox System.Object | |
PS> $asmInfo.GetTypes() | ? { $_.Name -eq 'messagebox' } | pfind -m 'show\(system\.string\)' | |
Method | |
------ | |
System.Windows.Forms.DialogResult Show(System.String) | |
PS> $asmInfo.GetTypes() | ? { $_.Name -eq 'messagebox' } | pfind -m 'show\(system\.string\)' | pget | clip # この結果については、System.Windows.Forms.v4.0.30319.v4.0.0.0.prig に貼り付けてください。 | |
PS> exit | |
PS> | |
Visual Studio に戻り、IsolatorMigrationDemo.v4.0.30319.v1.0.0.0.prig と System.Windows.Forms.v4.0.30319.v4.0.0.0.prig に各々の間接設定を貼り付けます。ビルドが成功したら、サンプルを移行していきますよ!
Example Test 1 - Simple test using MessageBox
Isolator は、プロファイリング API による強力なメソッドの入れ替え機能に加え、JustMock と同様、Mock Object を生成する機能を持っています。Prig はそのような機能をサポートしていませんが、最初に説明した通り、Moq と連携することで、それを実現することができましたね。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Test] | |
public void MessageBoxShow_should_be_callable_indirectly() | |
{ | |
using (new IndirectionsContext()) | |
{ | |
// Arrange | |
var mockMessageBox = new Mock<IndirectionFunc<string, DialogResult>>(); | |
mockMessageBox.Setup(_ => _(string.Empty)).Returns(DialogResult.OK); | |
PMessageBox.ShowString().Body = mockMessageBox.Object; | |
// Act | |
MessageBox.Show("This is a message"); | |
// Assert | |
mockMessageBox.Verify(_ => _("This is a message")); | |
} | |
} |
Isolate.WhenCalled は、Prig の間接スタブ(この場合、PMessageBox.ShowString().Body)に、Moq.Mock
Example Test 2 - Complex Test
「複雑な」と付いていますが、そう難しいものではありません ( ̄ー ̄)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Test] | |
public void UserOfSomeClassDoSomething_should_show_MessageBox_if_an_exception_is_thrown() | |
{ | |
using (new IndirectionsContext()) | |
{ | |
// Arrange | |
PSomeClass.MyMethod().Body = () => { throw new Exception("foo"); }; | |
var mockMessageBox = new Mock<IndirectionFunc<string, DialogResult>>(); | |
mockMessageBox.Setup(_ => _(string.Empty)).Returns(DialogResult.OK); | |
PMessageBox.ShowString().Body = mockMessageBox.Object; | |
// Act | |
var user = new UserOfSomeClass(); | |
user.DoSomething(); | |
// Assert | |
mockMessageBox.Verify(_ => _("Exception caught: foo")); | |
} | |
} |
特別な条件が無いのであれば、Isolate.WhenCalled(..).WillThrow は、Prig の間接スタブ(この場合、PSomeClass.MyMethod().Body)に、直接例外をスローする関数を割り当てることで、置き換えることができます。Isolate.WhenCalled(..).WillReturn や Isolate.Verify.WasCalledWithExactArguments は、前に説明しましたので・・・おっと、これで全部です!
ちなみに、対象が、MessageBox 処理があるにも関わらずテストコードを書きたくなるほど複雑な場合、設計をしくじっている可能性が高いと、個人的には思います。既存のコードやレガシーコードに対しては仕方がないでしょうが、こんなライブラリのような闇の力を、新規のプロダクトコードには使わなくて済むことを願いたいものですね (^^ゞ
0 件のコメント:
コメントを投稿