Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Mocking in Rust Applications
Search
taiki45
September 10, 2024
Technology
2
610
Mocking in Rust Applications
Talk at "RustのWebアプリ開発 LT道場 〜テスト編〜"
https://findy.connpass.com/event/327824/
taiki45
September 10, 2024
Tweet
Share
More Decks by taiki45
See All by taiki45
Error Handling in Rust Applications
taiki45
3
650
Efficient Platform for Security and Compliance
taiki45
4
1.5k
RustでAWS Lambda functionをいい感じに書く
taiki45
2
670
SPIFFE Meetup Tokyo #2 LT: Envoy SDS
taiki45
0
770
builderscon Tokyo 2019: Intro Service Mesh
taiki45
6
3.4k
NoOps Meetup Tokyo #7: 入門サービスメッシュ
taiki45
4
1.9k
CloudNative Days Tokyo 2019: Understanding Envoy
taiki45
3
3.5k
Cloud Native Meetup Tokyo #8 ServiceMesh Day Recap
taiki45
2
390
EnvoyCon 2018: Building and operating service mesh at mid-size company
taiki45
3
4.5k
Other Decks in Technology
See All in Technology
AIのグローバルトレンド 2025 / ai global trend 2025
kyonmm
PRO
1
120
MCP認可の現在地と自律型エージェント対応に向けた課題 / MCP Authorization Today and Challenges to Support Autonomous Agents
yokawasa
5
1.8k
Findy Freelance 利用シーン別AI活用例
ness
0
300
生成AI時代におけるAI・機械学習技術を用いたプロダクト開発の深化と進化 #BetAIDay
layerx
PRO
1
1k
Agent Development Kitで始める生成 AI エージェント実践開発
danishi
0
120
AI時代の経営、Bet AI Vision #BetAIDay
layerx
PRO
1
1.7k
S3 Glacier のデータを Athena からクエリしようとしたらどうなるのか/try-to-query-s3-glacier-from-athena
emiki
0
180
LLM 機能を支える Langfuse / ClickHouse のサーバレス化
yuu26
4
290
データモデリング通り #2オンライン勉強会 ~方法論の話をしよう~
datayokocho
0
110
【CEDEC2025】ブランド力アップのためのコンテンツマーケティング~ゲーム会社における情報資産の活かし方~
cygames
PRO
0
240
LLMで構造化出力の成功率をグンと上げる方法
keisuketakiguchi
0
430
バクラクによるコーポレート業務の自動運転 #BetAIDay
layerx
PRO
1
840
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1370
200k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.6k
The Invisible Side of Design
smashingmag
301
51k
BBQ
matthewcrist
89
9.8k
The Language of Interfaces
destraynor
158
25k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
1.8k
A designer walks into a library…
pauljervisheath
207
24k
Mobile First: as difficult as doing things right
swwweet
223
9.9k
Facilitating Awesome Meetings
lara
54
6.5k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.8k
Intergalactic Javascript Robots from Outer Space
tanoku
272
27k
Transcript
© 2024 Finatext Holdings Ltd. Mocking in Rust Applications Taiki
Ono, Finatext
© 2024 Finatext Holdings Ltd. Taiki Ono @taiki45 1
None
© 2024 Finatext Holdings Ltd. 1. モックするまでの道のり 2. モックを定義する・使う 例として使ったコードは
https://github.com/Finatext/orgu に全貌あります 今回の話は単体テストくらいの粒度のテストをスコープにしています 目次 3
© 2024 Finatext Holdings Ltd. モックするまでの道のり 4
© 2024 Finatext Holdings Ltd. テスト対象のロジックは外部依存について差し替え可能であることが望ましいです(後述) Rustでは交換可能性はGenericsまたはTrait Objectsを使って実現できます • Generics
(+ Trait Bounds): コンパイル時に具体的な型が分かるケースで利用します。コンパイラがそれぞ れの具体的な型用のコードを生成する。静的ディスパッチ • Trait Objects: コンパイル時に具体的な型が分からないケースで利用します。実行時のメソッド呼び出し時 に仮想関数テーブルを参照して実際の呼び出し関数(メソッド)を決定します。動的ディスパッチ 交換可能性を導入する 5
© 2024 Finatext Holdings Ltd. 非同期ジョブのロジックという例: 「GitHub Checks APIを使ってCheckRunを作成して、Git cloneでリポジトリをクローンして、指定された外部
コマンドを実行する」 テスト時にモックしたい部分 • GitHub APIを呼ぶ: GithubClient trait • Git clone: Checkout trait →このケースでは例えば、Handlerという構造体を定義してそれぞれの外部依存を持たせる 交換可能性の例 6
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: GithubClient trait 7
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: Checkout trait 8
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: Handler 9
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: Handlerの初期化関数 10
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: ドメインロジック 11
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: 初期化 12
© 2024 Finatext Holdings Ltd. 静的ディスパッチのアプローチ: テスト時の初期化 13
© 2024 Finatext Holdings Ltd. 動的ディスパッチのアプローチ: Handler定義 14 ※動的ディスパッチ
© 2024 Finatext Holdings Ltd. 動的ディスパッチのアプローチ: 初期化 15
© 2024 Finatext Holdings Ltd. ケースバイケース Webアプリケーションの場合はIOの方がはるかにでかいので、生産性その他で決めるといいです 静的ディスパッチ vs 動的ディスパッチ
16
© 2024 Finatext Holdings Ltd. axum crateのStateのような仕組みを使う http crateのRequest構造体にはexstensionの仕組みがあるので、このexstensionに状態を毎回セットする tower::Serviceを作ると同じようなことが実現できる(はず)
ある程度の規模以上だと依存管理が煩雑になりそうなのでDependency Injdectionライブラリが有効そうだが少な い。DIパターンもデファクトがあるわけではなさそうなので今後の発展に期待(っぽい) Webアプリケーションでの交換可能性の実現 17
© 2024 Finatext Holdings Ltd. Webアプリケーションでの交換可能性の実現 18
© 2024 Finatext Holdings Ltd. モックを定義する・使う 19
© 2024 Finatext Holdings Ltd. • #[automock] ◦ 先の例のような典型的なケースではこのattribute macroで自動生成する
• mock! ◦ #[automock]マクロではダメなケースでこのproc macroで半手動(?)で生成する 名前に "Mock" prefixが付いた構造体が定義されるので、::newか::defaultで構造体を初期化する モック構造体の専用のメソッドを使ってモック対象のtraitのメソッド呼び出しのexpectationを設定する Expectation設定用のメソッド名は "expect_<original_method_name>" という規約 デストラクタで設定されたexpectationを検証する mockall crate 20
© 2024 Finatext Holdings Ltd. 例: モック定義 21
© 2024 Finatext Holdings Ltd. 例: モックを使う 22
© 2024 Finatext Holdings Ltd. 例: メソッドの引数の検証 23
© 2024 Finatext Holdings Ltd. • 構造体の実装のモックはできるが名前空間上でハック(?)が必要でやや微妙 ◦ 後述 •
Associated functions(static methods?)のモックはexpectationの設定がグローバルになるので、テスト の並列実行で同期ロジックが必要 ◦ なるべく避けたい • モジュール上の関数もモック可能だが名前空間上のハックが必要、かつexpectationの設定がグローバルにな る ◦ なるべく避けたい • モック対象のtraitのメソッドが参照を返す場合は制限あり • モック対象のtraitのメソッドの返り値がimpl Traitの場合は、mockall内部でBox<dyn Trait>に変換するの で制限あり • モック対象のtraitのメソッドの返り値がimpl Futureの場合は、返り値をpinningする必要あり ◦ 実際はasyncキーワードとasync-trait crateを使うことが多い(?) ◦ 後述 ドキュメントとexamplesがかなり丁寧でその他のケースも網羅してるので困った時はどうぞ mockallの注意点 24
© 2024 Finatext Holdings Ltd. async_traitマクロの手前にautomockマクロを置く。言い換えると、async_traitマクロで書き換えられた後の コードに対してautomockマクロでモック生成する async_traitマクロがその名前でimportされている必要あり。内部で使っているっぽい async-trait crateとの併用
25
© 2024 Finatext Holdings Ltd. 構造体の実装のモック 26
© 2024 Finatext Holdings Ltd. Associated Functionsの交換 27
© 2024 Finatext Holdings Ltd. 実用Rustアプリケーション開発 28 https://zenn.dev/taiki45/books/pragmatic-rust-application-development
None