Moq & Fakes Framework を使った実践的ユニットテスト - BuildInsider

9,977 views

Published on

2013/6/8 BuildInsider
モックを使わないユニットテストは全ての依存先クラスの挙動も含めて考慮しなくてはならないため、まるで結合テストのようになってしまいます。
本セッションではモックを使用した実践的なユニットテストの実装方法をご紹介します。

Published in: Technology
0 Comments
22 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,977
On SlideShare
0
From Embeds
0
Number of Embeds
2,874
Actions
Shares
0
Downloads
0
Comments
0
Likes
22
Embeds 0
No embeds

No notes for slide

Moq & Fakes Framework を使った実践的ユニットテスト - BuildInsider

  1. 1. Moq & Fakes Framework を使った実践的ユニットテスト株式会社ネクストスケープアーキテクト上坂 貴志http://www.nextscape.net/
  2. 2. 2セッションのゴール• モックとは何かがわかる• モックを使うとどんな良いことがあるかがわかる• モック導入のためのアーキテクチャがわかる• モックを使用したユニットテストを実プロジェクトに導入する!
  3. 3. 3ごめんなさい、CM です• 株式会社 NEXTSCAPE というシステム開発会社です。
  4. 4. 4ごめんなさい、CM です• オフィシャルな謳い文句• Microsoft Partner of the Year 2012 Windows Azure受賞!• 2013 Microsoft Worldwide Partner Award (Cloud Partner of the Year) ファイナリスト!• Windows Azure 取扱高がアジア No.1 !• PlayReadyについて、アジア・パシフィックにおける Microsoft 唯一の戦略パートナー!(※PlayReady…Microsoft の デジタル著作権管理プラットフォーム)• Sitecore認定パートナー!MVP保持者日本最多!(※Sitecore…世界50ヵ国以上、世界有名ブランド3000社以上が導入した Web CMS & Digital MarketingPlatform)• 株式会社 豆蔵のグループ会社です。
  5. 5. 5ごめんなさい、CM です• 人材募集な内容• .NET 、特に C#.NET による開発が大多数です。(iOSアプリ開発もしてます!)• 二次請けは一切しません。していません。• プログラミング大好き!新しい技術大好き!という人、多数。というかそういうタイプの人が社風に合うみたい?• こっそりと Microsoft MVP がちらほら。• アジャイル開発推進中。• 社長「工数ベースで売上を考える時代は終わった!」(詳しくは面接で!)• 中途採用絶賛強化中!.Net エンジニア集まれ!
  6. 6. 6セッション内容1. 改めてモックとは2. モックを使用するメリット3. Moq とは4. Fakes Framework とは5. テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  7. 7. 1.改めてモックとは2. モックを使用するメリット3. Moq とは4. Fakes Framework とは5. テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  8. 8. 8改めてモックとは• テスト対象のクラスが依存するクラスの代わりとなるものテスト対象クラス---------------------テスト対象メソッドテストクラス--------------------テストメソッド依存クラスA---------------------メソッドA依存クラスB---------------------メソッドB引数パターン1引数パターン2・・・引数A引数B戻り値A戻り値Bモックで置き換えるモックで置き換える
  9. 9. 9改めてモックとは• 一般的なモックの使用方法テスト対象クラス---------------------テスト対象メソッドテストクラス--------------------テストメソッド依存クラスA---------------------メソッドA引数パターン1戻り値A<依存クラスA>Mock Object1. モック化する依存クラス、または Interface を指定して生成2. モック化するメソッドを指定して戻り値をセット3. モックを渡す4. テスト対象メソッドを起動モック化する対象<依存クラスA>Mock Objectモックにセットした戻り値になる
  10. 10. 1. 改めてモックとは2.モックを使用するメリット3. Moq とは4. Fakes Framework とは5. テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  11. 11. 11モックを使用するメリット• 依存クラスのバグを気にしなくて良いテスト対象クラス---------------------テスト対象メソッドテストクラス--------------------テストメソッド依存クラスA---------------------メソッドA引数 引数戻り値Aどっちが原因かわからない?戻り値Assert失敗!モックで置き換える原因はこっち!
  12. 12. 12モックを使用するメリット• テスト範囲を汚染しないテスト対象クラス---------------------テスト対象メソッドテストクラス--------------------テストメソッド依存クラスA---------------------メソッドA引数 引数A戻り値A戻り値モックで置き換える戻り値Aは”hogehoge”ね!何をセット?何を渡されても戻り値に関係ない戻り値は”hogehoge”
  13. 13. 13モックを使用するメリット• データベースにテストデータを用意しないで済むテスト対象クラス---------------------テスト対象メソッドテストクラス--------------------テストメソッド引数 引数ADataTableEntity戻り値DB 取得結果はこの Entity ね!データアクセスクラス--------------------ADO.NET,Entity Framework, etcSelectUpdateInsertDataモックで置き換えるTran 1MasterATran NMasterTran 2・・・MasterA戻り値となるDataTable,Entity はテストパターンに合わせて自由自在
  14. 14. 1. 改めてモックとは2. モックを使用するメリット3.Moq とは4. Fakes Framework とは5. テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  15. 15. 15Moq とは• オープンソースモックライブラリ。商用可能。• NuGet で 簡単に DLL ダウンロード &参照追加• 特徴1. ラムダ式によって型、メソッド、戻り値の指定2. インターフェース, クラス (抽象クラスも含む)どちらもモック化可能• クラスの場合、public な仮想メソッドのみモック化可能)3. モック化したメソッドの引数に Moq.It.IsAny<T>()を指定することで仮引数に渡された値を無視することが簡単にできる4. 静的メソッドはモック不可
  16. 16. 16• カートに 商品を追加するシナリオMoqの使用方法StockService----------------------------------+ int CurrentQuantity(int productId)+ bool ProvisionTemporary(int productId, out int tempProvisionId)+ bool Provision(int tempProvisionId)Cart---------------------+ bool Add(int productId)X現在の在庫数 は?( CurrentQuantity )商品を仮押さえ( provisionTemporary)仮押さえ Id (temporaryProvisionId)falseAlt[在庫数 <1]trueXX
  17. 17. 17Moqの使用方法StockService---------------------<virtual>+ int CurrentQuantity(int productId)Cart---------------------+ bool Add(int productId)テストクラス--------------------テストメソッド• 本当に Mock 化したメソッドが使用されたのかを確認する• 何回 Mock 化したメソッドが使用されたのかを確認 するVerify メソッドを使う
  18. 18. 1. 改めてモックとは2. モックを使用するメリット3. Moq とは4.Fakes Framework とは5. テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  19. 19. 19Fakes Framework とは• Micorosoft製モックフレームワーク。(Visual Studio 2012 Premium, Ultimateでのみ使用可)• Microsoft.QualityTools.Testing.Fakes へ参照追加• 特徴1. 事前に Mock用のクラスを生成• 参照設定中の DLL を右クリックで指定すると自動的に生成2. 大きく機能が二つにわかれている• インターフェース, 抽象クラス のモックは Stub(Moq とほぼ同じ機能と考えればOK)• クラスのモックは Shims(ほぼなんでもモック化可能。public 仮想メソッド でなくてもモック可能、静的メソッドもモック化可能!)
  20. 20. 20Fakes Framework の使用方法Cart---------------------+ bool Add(int productId)テストクラス--------------------テストメソッド何も渡さないただ起動するだけStockService---------------------<virtual>+ int CurrentQuantity(int productId)• 本当に Mock 化したメソッドが使用されたのかを確認する?• 何回 Mock 化したメソッドが使用されたのかを確認 する?そんな機能はありません・・・
  21. 21. 21Fakes Framework の使用方法(依存クラスがInterface を実装している場合)Cart---------------------+ bool Add(int productId)テストクラス--------------------テストメソッド IStockServiceStockService---------------------<virtual>+ int CurrentQuantity(int productId)• 本当に Mock 化したメソッドが使用されたのかを確認する?• 何回 Mock 化したメソッドが使用されたのかを確認 する?やっぱりそんな機能はありません・・・
  22. 22. 1. 改めてモックとは2. モックを使用するメリット3. Moq とは4. Fakes Framework とは5.テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  23. 23. 23テスタビリティの高いアーキテクチャ• 依存クラスをモックで切り替えられるようにするためにはアーキテクチャに従った実装が必要Mockを使わない?メソッド内のローカル変数はモック化できない!Test Projectさっきのシナリオでのテスト実装はこうだった
  24. 24. 24テスタビリティの高いアーキテクチャ• 依存クラスをモックで切り替えられるようにするためにはアーキテクチャに従った実装が必要• 依存オブジェクトはプロパティで持つ!• メソッド内ではオブジェクト生成しない!Test ProjectMock使用してる!MockMock
  25. 25. 25テスタビリティの高いアーキテクチャ• 依存オブジェクトの生成 その1依存オブジェクトの生成はデフォルトコンストラクタで!コンストラクタのオーバーロードは必ずデフォルトコンストラクタを呼ぶ!
  26. 26. 26テスタビリティの高いアーキテクチャ• 依存オブジェクトの生成 その2CartStockServiceDIContainerGive me Cart objectHere you are !!CreateCreateInjectionPropertyInjectionConstructorInjection
  27. 27. 27CartCartテスタビリティの高いアーキテクチャ• サービスを格納するプロパティは internal にTest ProjectASP.NET MVCController Class見えないよ?テストプロジェクト以外からは見ちゃだめ!・・・って口で言っても守ってくれる保証はないなぁASP.NET MVCController ClassTest Project見えてる!
  28. 28. 28Cartテスタビリティの高いアーキテクチャ• サービスを格納するプロパティは internal にTest Project見えてる!ASP.NET MVCController Class追記AssermblyInfo の変更でテストクラスからだけ見えるように
  29. 29. 29ShimsContext 上で実行するテスタビリティの高いアーキテクチャ• 既に構築済みのシステムはどうするか?• 絶対に実装済みの箇所を触れないなら、Fakes Framework 一択!Cart---------------------+ bool Add(int productId)テストクラス--------------------テストメソッドShimsモックStockService---------------------<virtual>+ int CurrentQuantity(int productId)
  30. 30. 1. 改めてモックとは2. モックを使用するメリット3. Moq とは4. Fakes Framework とは5. テスタビリティの高いアーキテクチャ6.実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  31. 31. 31実例:DBを使用しないユニットテスト• 説明の前提となる構成1. DBアクセスには Entity Framework 使用2. Serviceレイヤーで直接 DB にアクセスしない3. Repositoryレイヤーのみが DB にアクセスする• Repository<T> クラスを用意• Repository <T>クラスは IRepository<T> インターフェースを実装• Repository<T> クラスの アクセス修飾子は internal• 全てのDBアクセスはこのクラスを通じてしか許さない• いわゆるリポジトリパターンってやつですService---------------------テスト対象クラス Repository<T>---------------------モック対象クラスIRepository<T> EntityFramework(DbContext)
  32. 32. 32実例:DBを使用しないユニットテスト• Repository クラスはこんな感じで使いますFactStock は、Model クラス(テーブルと1 : 1でVS が自動生成)Filter は IRepository<T> のメソッド。戻り値は IList<T>Sum は Linq to Object のメソッド
  33. 33. 33実例:DBを使用しないユニットテストMoq 版右へ続くテスト対象 CurrentQuantity メソッドCallback メソッドは、引数を受け取ることができる
  34. 34. 34実例:DBを使用しないユニットテストFakes Stub 版右へ続くテスト対象 CurrentQuantity メソッドDelegate の引数でメソッドの引数を受け取ることができる
  35. 35. 35まとめ• モックとは何かがわかる• テスト対象が依存するクラスを入れ替えるもの• ほとんどのモックライブラリの使い方は似ている• モックを使うとどんな良いことがあるかがわかる• 依存クラスのバグを気にしなくて良い• テスト範囲を汚染しない• データベースにテストデータを用意しないで済む• モック導入のためのアーキテクチャがわかる• 依存オブジェクトはプロパティで持つ• メソッド内ではオブジェクト生成しない• 生成依存の解決は DI コンテナがお薦め• モックを使用したユニットテストを実プロジェクトに導入する!• Repository パターンを使用して、DBに依存しないテスト
  36. 36. 1. 改めてモックとは2. モックを使用するメリット3. Moq とは4. Fakes Framework とは5. テスタビリティの高いアーキテクチャ6. 実例:DBを使用しないユニットテスト7. まとめ8. おまけ(ShimによるDbContextモック化)
  37. 37. 注意!難易度高め!
  38. 38. 38実例:DBを使用しないユニットテストFakes Shim 版• StockService.CurrentQuantity メソッド内でDbContextを継承するクラスを 生成している場合Mock化できない• Mock 化可能にするために DbSet<T> → IDbSet<T>※自動生成なので、T4テンプレートを修正DbContextを継承しているクラス
  39. 39. 39実例:DBを使用しないユニットテストFakes Shim 版右へ続くテスト対象 CurrentQuantity メソッドWhereで指定された Expression を受け取るdb.FactStocks の ShimIDbSet<FactStock> のStub を返却まだ続く
  40. 40. 40実例:DBを使用しないユニットテストFakes Shim 版Where に指定された Expression をテストするために、System.Linq.IQueryable.Where メソッドをモック化できなくないけど、難しいねRepository パターンの方が簡単だよ!
  41. 41. ありがとうございました

×