$30 off During Our Annual Pro Sale. View Details »
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
670
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
730
Efficient Platform for Security and Compliance
taiki45
5
1.6k
RustでAWS Lambda functionをいい感じに書く
taiki45
2
760
SPIFFE Meetup Tokyo #2 LT: Envoy SDS
taiki45
0
800
builderscon Tokyo 2019: Intro Service Mesh
taiki45
6
3.5k
NoOps Meetup Tokyo #7: 入門サービスメッシュ
taiki45
4
1.9k
CloudNative Days Tokyo 2019: Understanding Envoy
taiki45
3
3.6k
Cloud Native Meetup Tokyo #8 ServiceMesh Day Recap
taiki45
2
400
EnvoyCon 2018: Building and operating service mesh at mid-size company
taiki45
3
4.6k
Other Decks in Technology
See All in Technology
A Compass of Thought: Guiding the Future of Test Automation ( #jassttokai25 , #jassttokai )
teyamagu
PRO
1
260
EM歴1年10ヶ月のぼくがぶち当たった苦悩とこれからへ向けて
maaaato
0
270
OCI Oracle Database Services新機能アップデート(2025/09-2025/11)
oracle4engineer
PRO
1
130
CARTAのAI CoE が挑む「事業を進化させる AI エンジニアリング」 / carta ai coe evolution business ai engineering
carta_engineering
0
560
LLM-Readyなデータ基盤を高速に構築するためのアジャイルデータモデリングの実例
kashira
0
240
Power of Kiro : あなたの㌔はパワステ搭載ですか?
r3_yamauchi
PRO
0
100
Ruby で作る大規模イベントネットワーク構築・運用支援システム TTDB
taketo1113
1
270
WordPress は終わったのか ~今のWordPress の制作手法ってなにがあんねん?~ / Is WordPress Over? How We Build with WordPress Today
tbshiki
1
710
モダンデータスタック (MDS) の話とデータ分析が起こすビジネス変革
sutotakeshi
0
470
「Managed Instances」と「durable functions」で広がるAWS Lambdaのユースケース
lamaglama39
0
310
因果AIへの招待
sshimizu2006
0
960
直接メモリアクセス
koba789
0
300
Featured
See All Featured
Facilitating Awesome Meetings
lara
57
6.7k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
21k
Side Projects
sachag
455
43k
Git: the NoSQL Database
bkeepers
PRO
432
66k
A better future with KSS
kneath
240
18k
Stop Working from a Prison Cell
hatefulcrawdad
273
21k
Fireside Chat
paigeccino
41
3.7k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
Scaling GitHub
holman
464
140k
The Cult of Friendly URLs
andyhume
79
6.7k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
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