組織駆動設計～監査～

以下の記事をベースに話を進めていきます。

https://qiita.com/sikimuOji/items/3cfb8c81f82e7f86f613

# ユニットテストという監査人
**システム概要**
**仕様１**．部下Aと部下Bの仕事だ正しいか監査する
**仕様２**．上司が部下Aと部下Bに仕事をさせているか監査する


# 監査前
部下Aは、商品名からケース当たりの本数を報告する。
部下Bは、発注数とケース当たりの本数から合計本数を計算する。
上司は、やってきた部下たちに指示を出して結果を報告する。

~~~java:上司.java
class 上司 {
    public int 合計本数の確認の指示を出す{
        部下A 太郎, 部下B 花子, 
        String 商品名, int 発注数){
        
        int ケース当たりの本数 = 太郎.ケース当たりの本数の報告(商品名);
        int 合計本数 = 花子.合計本数の計算(ケース当たりの本数, 発注数);

        return 合計本数;        
    }
}
~~~

~~~java:部下A.java
class 部下A {
    public int ケース当たりの本数の報告(String 商品名){
        if(商品名.equals("コーラ")){
            return 12;
        }
        if(商品名.equals("サイダー")){
            return 24;
        }
        return 20;//他は20本
    }
}
~~~

~~~java:部下B.java
class 部下B {
    public int 合計本数の計算(int ケースあたりの本数, int 発注数){
        
        return ケース当たりの本数 * 発注数;        
    }
}
~~~

# 部下の監査
部下Aと部下Bが想定通りなのか監査する。
パターンが固定数のものは可能な限り監査する。
パターンが出せないものは最低２パターンは監査する。

~~~java:監査員.java
public class 監査員 {
    @Test
    public void 部下Aに関する監査() {
        部下A 太郎 = new 部下A();
        assertEquals(太郎.ケース当たりの本数の報告("コーラ"), 12);
        assertEquals(太郎.ケース当たりの本数の報告("サイダー"), 24);
        assertEquals(太郎.ケース当たりの本数の報告("紅茶"), 20);
    }

    @Test
    public void 部下Bに関する監査() {
        部下B 花子 = new 部下B();
        assertEquals(花子.合計本数の計算(12, 3), 36);
        assertEquals(花子.合計本数の計算(24, 2), 48);
    }
~~~
~~~java:部下A.java
~省略~
~~~
~~~java:部下B.java
~省略~
~~~

# 上司への監査
部下の動きはすでに監査済みなので、上司の監査で部下が正しい動きなのか把握する必要はない。

~~~java:監査員.java
public class 監査員 {

    @Test
    public void 上司に関する監査() {
        上司 斎藤 = new 上司();
        部下A 太郎 = new 部下A();
        部下B 花子 = new 部下B();
        assertEquals(斎藤.合計本数の確認の指示を出す(太郎,花子, "コーラ", 10), 120);

        上司 斎藤 = new 上司();
        部下A 太郎 = new 部下A();
        部下B 花子 = new 部下B();
        assertEquals(斎藤.合計本数の確認の指示を出す(太郎,花子, "紅茶", 3), 60);
    }

    @Test
    public void 部下Aに関する監査() {
        部下A 太郎 = new 部下A();
        assertEquals(太郎.ケース当たりの本数の報告("コーラ"), 12);
        assertEquals(太郎.ケース当たりの本数の報告("サイダー"), 24);
        assertEquals(太郎.ケース当たりの本数の報告("紅茶"), 20);
    }

    @Test
    public void 部下Bに関する監査() {
        部下B 花子 = new 部下B();
        assertEquals(花子.合計本数の計算(12, 3), 36);
        assertEquals(花子.合計本数の計算(24, 2), 48);
    }
~~~
~~~java:部下A.java
~省略~
~~~
~~~java:部下B.java
~省略~
~~~

# 覆面調査員(モックオブジェクト)
Aになりきった覆面調査員が常に50を返すことで部下Bへの指示が正しいか監査する。
Bになりきった覆面調査員が20を渡されたときにだけ128を渡すことで部下Aへの指示が正しいか監査する。
~~~java:監査員.java
public class 監査員 {

    @Test
    public void 上司に関する監査() {
        上司 斎藤 = new 上司();
        部下A 太郎 = new 部下A();
        部下B 花子 = new 部下B();
        assertEquals(斎藤.合計本数の確認の指示を出す(太郎,花子, "コーラ", 10), 120);

        上司 斎藤 = new 上司();
        部下A 太郎 = new 部下A();
        部下B 花子 = new 部下B();
        assertEquals(斎藤.合計本数の確認の指示を出す(太郎,花子, "紅茶", 3), 60);
    }

    @Test
    public void 上司に関する覆面A調査員を使っての監査() {
        上司 斎藤 = new 上司();

        部下A 覆面太郎 = mock(部下A.class);
        when(覆面太郎.ケース当たりの本数の報告(anyString())).thenReturn(50);

        部下B 花子 = new 部下B();
        assertEquals(斎藤.合計本数の確認の指示を出す(太郎,花子, "紅茶", 6), 300);
    }

    @Test
    public void 上司に関する覆面B調査員を使っての監査() {
        上司 斎藤 = new 上司();

        部下A 太郎 = new 部下A();

        部下B 覆面花子 = mock(部下B.class);
        when(覆面花子.合計本数の計算(20)).thenReturn(128);

        assertEquals(斎藤.合計本数の確認の指示を出す(太郎,花子, "紅茶", 6), 128);
    }

    @Test
    public void 部下Aに関する監査() {
        部下A 太郎 = new 部下A();
        assertEquals(太郎.ケース当たりの本数の報告("コーラ"), 12);
        assertEquals(太郎.ケース当たりの本数の報告("サイダー"), 24);
        assertEquals(太郎.ケース当たりの本数の報告("紅茶"), 20);
    }

    @Test
    public void 部下Bに関する監査() {
        部下B 花子 = new 部下B();
        assertEquals(花子.合計本数の計算(12, 3), 36);
        assertEquals(花子.合計本数の計算(24, 2), 48);
    }
~~~
~~~java:部下A.java
~省略~
~~~
~~~java:部下B.java
~省略~
~~~

覆面調査員についてはもう少し、精査を予定しています。