導入
DB・外部API・時刻など「本物を使うとテストが遅い・不安定」な依存先を、偽物(モック)に差し替えるNuGetライブラリがMoqです。DIP(抽象への依存)が前提になります。
図解
flowchart LR
T["テスト対象"] --> I["インターフェース(抽象)"]
I -->|本番| R["本物(DB/API)"]
I -->|テスト| M["モック(Moqが生成)<br/>「こう返す」と指定"]
style M fill:#e8f5e9
サンプル
// --- Moq の記法(読み物) ---
// var mock = new Mock<IDiscountService>();
// mock.Setup(s => s.GetRate("VIP")).Returns(0.1m); // 振る舞いを指定
// var calc = new PriceCalculator(mock.Object);
// Assert.Equal(900m, calc.Calculate("VIP", 1000m));
// mock.Verify(s => s.GetRate("VIP"), Times.Once()); // 呼ばれたか検証
// ブラウザでは「手動フェイク」で同じ考え方を再現(Moqはこれを自動生成する道具)
var calc = new PriceCalculator(new FakeDiscount(0.1));
Console.WriteLine(calc.Calculate(1000)); // 900
interface IDiscount { double Rate(); }
class FakeDiscount : IDiscount // 手動モック(固定値を返す偽物)
{
private readonly double _rate;
public FakeDiscount(double rate) => _rate = rate;
public double Rate() => _rate;
}
class PriceCalculator
{
private readonly IDiscount _discount;
public PriceCalculator(IDiscount discount) => _discount = discount;
public int Calculate(int price) => (int)(price * (1 - _discount.Rate()));
}
- Moqは
new Mock<IXxx>()で偽物を作り、Setup(...).Returns(...)で振る舞いを指定する Verify(...)で「その呼び出しが行われたか」も検証できる- 本質は「インターフェースの手動実装(フェイク)を自動生成してくれる道具」
演習
var greeter = new Greeter(new FakeClock(2026));
Console.WriteLine(greeter.Greet()); // あけましておめでとう
// TODO: IClock(Year()→int)を実装する FakeClock を定義してください(固定の年を返す)
interface IClock { int Year(); }
class Greeter
{
private readonly IClock _clock;
public Greeter(IClock clock) => _clock = clock;
public string Greet() => _clock.Year() == 2026 ? "あけましておめでとう" : "こんにちは";
}
___
- 期待される出力:
あけましておめでとう
ヒント1を見る
class FakeClock : IClock { private readonly int _y; public FakeClock(int y) => _y = y; public int Year() => _y; }
ヒント2を見る
固定値を返す偽物を注入すると、時刻に依存せずテストできます
まとめ
- Moqは依存先を偽物(モック)に差し替えるライブラリ
Setupで振る舞い指定、Verifyで呼び出し検証- 仕組みは素のC#の手動フェイクと同じ(DIが前提)
次回: 読みやすい検証を書くFluentAssertionsです。