モックとスタブとCQRS

## はじめに
　ユニットテストを実装していると、何気ない感じで当たり前のようにMoqとかのツールを使っていますが、どんな使い方が正解なのかという意識をあまりしていませんでした。
　改めて、ユニットテストについて学ぶ機会があり、その際にMicrosoft Documentにこんな記載を見つけました。

 
https://docs.microsoft.com/ja-jp/dotnet/core/testing/unit-testing-best-practices
>　テストに関して、"モック" という用語は残念ながら誤用されることがしばしばあります。
>>:::note warn
>>重要
この用語を正確に理解することが重要です。 スタブを "モック" と名付けた場合、他の開発者はあなたの意図を誤って解釈してしまいます。
>>:::

　モックとスタブは違う。たまに聞く言葉なのですが、何が具体的に違うのか、なかなかすっきりしません。
　とりあえず同サイトではこんな説明の仕方をしています。
>モックとスタブに関する重要な留意点として、モックとスタブはよく似ていますが、モック オブジェクトに対してはアサートを行うのに対し、スタブに対してはアサートを行いません。

　どういうことなのか。これについて自分なりに理解した範囲ですが記事にさせていただきます。

## テストダブル(double) -- mock, spy, stub, dummy, fake
　余談ですが、ダブルと聞いてHunterxHunterでカストロが念で自分の分身を作った場面を思い出します。
　実際のところ、このテストで使用するダブルというのは、映画などの「スタントダブル」(Stunt double)に由来するそうです。
　スタントマンといえば、ビルから飛び降りたり格闘シーンといった危険な場面に使用される代役のことですね。つまり、本物のように見せた代理人ということになります。
　この概念をコーディングに応用したのが「テストダブル」ということになります。

　この「テストダブル」には5つのバリエーションがあり、それがmock, spy, stub, dummy, fakeです。
　テストツールでも、mockという呼び方をするものもいれば、spyと呼んでいるものもあります。
　実際のところは、これはモックとスタブの２つのタイプに分類することができます。

```mermaid
graph TD;
    テストダブル-->モック:mock,spy;
    テストダブル-->スタブ:stub,dummy,fake;
```

### モック(Mock)とスタブ(Stub)の違い
　モックは、依存関係を<font color="Crimson">**エミュレート**</font>し、さらにそのメソッドの<font color="Crimson">**結果(副作用)**</font>を<font color="Crimson">**調べる**</font>ために使用します。
　スタブは、依存関係を<font color="Crimson">**エミュレート**</font>してデータを<font color="Crimson">**取得**</font>するために使用します。

　ここがポイントですが、英語にすると分かりやすいかもしれません。
- モックは、<em>Emulate + Outcoming + Examine</em>
- スタブは、<em>Emulate + Incoming</em>

このOutcoming, Incomingを送信・受信と翻訳して解釈している例もありますが、自分にはあまりイメージしにくかったです。

むしろ重要な違いは、このExamineがあるかどうかというところです。
さきほどのMicrosoft Documentの引用を思い出してください。こう書いてあったはずです。
>モック オブジェクトに対してはアサートを行うのに対し、スタブに対してはアサートを行いません

#### モックとして扱う例
```C#
[Fact]
public void Send_Email_Test(){
    // arrange
    var mock = new Mock<IEmailService>();
    var sut = new SenderClass(mock.Object);
    
    // act
    sut.SendEmail("mail@example.com");

    // assertion
    mock.Verify(x => x.SendingEmail("mail@example.com"), Times.Once);
}
```
この場合、mockはMockツールで生成されたモックとなり、モックなのでsut[^1]でSendEmailメソッドが呼び出された時に、IEmailServiceのモックでSendingEmailメソッドが呼ばれているか検証しています。
つまり、モックは、エミュレートして、実際のその副作用を検証するという役割を果たしています。

#### スタブとして扱う例
```C#
[Fact]
public void Create_Report_Test(){
    // arrange
    var stub = new Mock<IBookRepositoty>();
    stub.Setup(x => x.GetBookCount()).Returns(100);
    var sut = new GetClass(stub.Object);

    // act
    Report report = sut.CreateReport();

    // assertion
    Assert.Equql(100, report.GetBookBookCount());
}
```
この場合、stubはMockツールで生成されたスタブとなり、スタブなのでsut[^1]でCreateReportメソッドが呼び出された時の、戻り値を提供しています。
スタブは値を返すだけであり、検証されることはありません。
[^1]:System Under Test の略
　テスト対象となるシステムという意味です

## SQRSとの関係
　ここで突然のようにSQRSを取り上げます。
　というのも、『Unit Testing Principles, Practices, and Patterns』(Vladimir Khorikov, 2020, MANNING)　という書籍に出会ったのですが、これが本当に分かりやすく、「なるほどー」と声を出してしまいました。もしご関係者がいらっしゃったら日本語訳を出してほしいです。

　以下の図をご覧ください。書籍からの引用です[^2]

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/3c86106a-b2e2-0460-13cb-fa0fb3cb49d3.png" width=400>

[^2]:『Unit Testing Principles, Practices, and Patterns』(Vladimir Khorikov, 2020, MANNING)
 Ch 5. Mocks and test fragility 
  5.1.4 Using mocks and stubs together

CQRS(もしくはCQS)について詳細な説明は省きますが、クエリをコマンドとクエリに分ける考え方です。
コマンドは、CRUDのうち、Create, Update, Deleteといったデータに対し副作用(side effects)を与えます。
クエリはSelectなので、副作用はなく値を返します。

これをモックとスタブに当てはめると、<font color="Crimson">**モックはコマンドに対応し、スタブはクエリと対応する**</font>ということです。

この表現を読んだとき、これまでのもやもやがすっきりしました。
モックは、結果(副作用)を与えるので、その作用についての検証が求められるわけです。
それに対しスタブは値を返すだけなので、検証対象とはならないということです。


どんな風に理解するのが分かりやすいかは人それぞれかと思いますが、自分はこれが一番すっきりする考えでしたので、記事としてご紹介させていただきました。