【要約】C#で new を差し替える実験的モックツールを作っている話 [Qiita_Trend] | Summary by TechDistill
> Source: Qiita_Trend
Execute Primary Source
// Problem
開発者が、依存関係を外部から注入できないレガシーなC#コードをテストする際、以下の課題に直面する。
- ・メソッド内で直接インスタンス化(
new)されているため、通常のMockでは差し替えが不可能。 - ・DIへのリファクタリングが困難な既存資産が現場には存在する。
- ・ILリライトを行うと型 identity が変化し、テスト側でオブジェクトをキャストできなくなる。
// Approach
開発者は、Mono.Cecilを用いてテスト対象のIL命令を動的に書き換える手法を採用した。
- ・
newobj命令をShimDispatcher.New<T>()へ置換する。 - ・書き換え済みアセンブリを、元の型と衝突しないよう別境界(
AssemblyLoadContext等)でロードする。 - ・型 identity 問題に対し、Reflectionを用いた
inspection APIを提供し、安全な検証を可能にする。
// Result
開発者は、このツールにより、DIが困難なコードに対しても以下の検証環境を得られる。
- ・
net8.0とnet48の両環境で動作する。 - ・
ReplaceNewAPIにより、簡潔な記述で差し替えが可能。 - ・
ShimsObject等により、複雑なオブジェクトグラフの検証ができる。 - ・今後はテストの並列実行性向上や、より複雑なオブジェクトグラフへの対応が課題となる。
Senior Engineer Insight
> レガシーコードのテスト容易性を高める「退避路」として、極めて実戦的なアプローチだ。DIへの移行が困難な大規模システムにおいて、品質を担保するための現実的な解となる。ただし、テストの並列実行不可や型 identity の制約は、大規模CI環境での運用コストを増大させる。あくまでリファクタリングを目的とした一時的な手段として、厳格に管理して導入すべき技術である。