ChatGPTにDI(依存性注入)について聞いてみました(続き)。
タイトル、文章、イラスト: ChatGPT
登場人物
- ミナト(左): 新人エンジニア。C#は書けるようになってきたけど、テストはまだ苦手。
- ハルカ(右): 頼れる先輩。説明が丁寧で、コーヒー片手に教えてくれる系。
1. テストってやっぱりむずかしい
ミナト「はぁ~……テスト、また失敗しました……」
ハルカ「お、珍しく落ち込んでるじゃん。どしたの?」
ミナト「ユニットテストを書いてたんですけど、依存してるクラスのせいでうまくいかなくて……」
ハルカ「ふむふむ。ちなみにどんな感じのコード?」
C#:
- public class MyApp
- {
- private Logger _logger = new Logger();
- public void Run() => _logger.Write("Hello");
- }
ミナト「この
Logger
が原因で……テストで何が出力されるか確認できないんですよ」
ハルカ「あー、それね。
new
しちゃってる問題だね」
2. テストしにくいコードの問題点
ハルカ「
MyApp
が自分でLogger
を作っちゃってるでしょ?これが密結合ってやつ。変更しづらくて、テストもしにくい」
ミナト「じゃあ、どうすればいいんですか……?」
ハルカ「そこでDIの出番ってわけよ!」
ミナト「あっ! あの
ILogger
とかで渡すやつですね!」
3. DIを使った「テストしやすい」形に書き換え
C#:
- public interface ILogger
- {
- void Write(string message);
- }
- public class ConsoleLogger : ILogger
- {
- public void Write(string message) => Console.WriteLine(message);
- }
- public class MyApp
- {
- private readonly ILogger _logger;
- public MyApp(ILogger logger)
- {
- _logger = logger;
- }
- public void Run() => _logger.Write("Hello");
- }
ミナト「なるほど~!
ILogger
をコンストラクタで受け取るようにすれば……」
ハルカ「そう! どんな
ILogger
を使うかは外の世界が決める。だからテストではモックを渡せばいいんだよ」
ミナト「モック……やってみます!」
4. モックでユニットテスト!
C#:
- public class MockLogger : ILogger
- {
- public string? LastMessage { get; private set; }
- public void Write(string message)
- {
- LastMessage = message;
- }
- }
- [TestMethod]
- public void Run_LogsHello()
- {
- var logger = new MockLogger();
- var app = new MyApp(logger);
- app.Run();
- Assert.AreEqual("Hello", logger.LastMessage);
- }
ミナト「あ! これ……ちゃんと中の
Write()
が呼ばれたか確認できてる!」
ハルカ「そうそう。これがDI×テストの醍醐味。振る舞いを記録できるから、見えない部分も検証できる」
ミナト「何をしたかが見えるって、安心感ありますね」
5. ちょっと休憩: DIとテストの関係を図にすると……
ハルカ「本番用もテスト用も、同じインターフェースに従うってのがポイント」
ミナト「インターフェース……大事ですね(復唱)」
6. テストしやすいコードは良いコード!
ハルカ「DIを使ってると、テストしやすい設計が自然にできるようになる」
ミナト「確かに!やってることはシンプルなのに、すごく柔軟になる気がします」
ハルカ「あと、テストのときだけDI登録を変えるって技もあるよ。Hostの
ConfigureServices
でテスト用サービスを渡したりね」
ミナト「え、それもできるんですか!? DI、奥が深いですね……」
ハルカ「でしょ?でも、入り口は今やったモックパターンだけで十分強い武器になるよ」
まとめ: テストが楽になると、コードも育てやすくなる!
DIで得られるテストのメリット | 内容 |
---|---|
差し替え可能 | テスト用実装に切り替えられる |
動作の中身が見える | モックで呼び出し確認できる/td> |
よりシンプルなテストが書ける | DIのおかげで依存解決が楽/td> |
自然と責務が分かれていく | 設計も整いやすくなる/td> |
0 件のコメント:
コメントを投稿