Commits

Shuji Watanabe committed ff7df5a

11章のコードを追加

Comments (0)

Files changed (27)

junit-examples/ch11_list.txt

+第11章
+------------------
+リスト11.1   src/main/java/ch11/DateDependencyExample.java
+リスト11.2   src/test/java/ch11/DateDependencyExampleTest.java
+リスト11.3   src/main/java/ch11/MethodExtractExample.java
+リスト11.4   src/test/java/ch11/MethodExtractExampleTest.java
+リスト11.5   src/main/java/ch11/withclass/DateFactory.java
+リスト11.6   src/main/java/ch11/withclass/DelegateObjectExample.java
+リスト11.7   src/main/java/ch11/withinterface/DateFactory.java
+リスト11.8   src/main/java/ch11/withinterface/DateFactoryImpl.java
+リスト11.9   src/main/java/ch11/withinterface/DelegateObjectExample.java
+リスト11.10  src/test/java/ch11/withinterface/DelegateObjectExampleTest.java
+リスト11.11  src/main/java/ch11/RandomNumberGenerator.java
+リスト11.12  src/main/java/ch11/RandomNumberGeneratorImpl.java
+リスト11.13  src/test/java/ch11/RandomNumberGeneratorFixedResultStub.java
+リスト11.14  src/main/java/ch11/Randoms.java
+リスト11.15  src/test/java/ch11/RandomsTest.java
+リスト11.16  src/test/java/ch11/RandomNumberGeneratorStub.java
+リスト11.17  src/main/java/ch11/UserDao.java
+リスト11.18  src/test/java/ch11/UserDaoStub.java
+リスト11.19  src/test/java/ch11/RandomsMockTest.java
+リスト11.20  src/main/java/ch11/SpyExample.java
+リスト11.21  src/test/java/ch11/SpyLogger.java
+リスト11.22  src/test/java/ch11/SpyExampleTest.java
+リスト11.23  src/test/java/ch11/MockitoExamples.java
+リスト11.24  src/test/java/ch11/MockitoExamples.java
+リスト11.25  src/test/java/ch11/MockitoExamples.java
+リスト11.26  src/test/java/ch11/MockitoExamples.java
+リスト11.27  src/test/java/ch11/MockitoExamples.java
+リスト11.28  src/test/java/ch11/MockitoExamples.java
+リスト11.29  src/test/java/ch11/MockitoExamples.java
+リスト11.30  src/test/java/ch11/SpyExampleTest.java
+リスト11.31  src/main/java/ch11/SpyExample.java
+リスト11.32  src/test/java/ch11/SpyExampleTest.java
+
+
+
+

junit-examples/src/main/java/ch11/DateDependencyExample.java

+package ch11;
+
+import java.util.Date;
+
+/**
+ * リスト11.1
+ * @author shuji.w6e
+ */
+public class DateDependencyExample {
+
+    Date date = new Date();
+
+    public void doSomething() {
+        this.date = new Date();
+        // なんらかの処理(省略)
+    }
+
+}

junit-examples/src/main/java/ch11/MethodExtractExample.java

+package ch11;
+
+import java.util.Date;
+
+/**
+ * リスト11.3
+ * @author shuji.w6e
+ */
+public class MethodExtractExample {
+
+    Date date = newDate();
+
+    public void doSomething() {
+        this.date = newDate();
+        // なんらかの処理(省略)
+    }
+
+    Date newDate() {
+        return new Date();
+    }
+}

junit-examples/src/main/java/ch11/RandomNumberGenerator.java

+package ch11;
+
+/**
+ * リスト11.11
+ * @author shuji.w6e
+ */
+public interface RandomNumberGenerator {
+
+    int nextInt();
+}

junit-examples/src/main/java/ch11/RandomNumberGeneratorImpl.java

+package ch11;
+
+import java.util.Random;
+
+/**
+ * リスト11.12
+ * @author shuji.w6e
+ */
+public class RandomNumberGeneratorImpl implements RandomNumberGenerator {
+    
+    private final Random rand = new Random();
+    
+    @Override
+    public int nextInt() {
+        return rand.nextInt();
+    }
+
+}

junit-examples/src/main/java/ch11/Randoms.java

+package ch11;
+
+import java.util.List;
+
+/**
+ * リスト11.14
+ * @author shuji.w6e
+ */
+public class Randoms {
+
+    RandomNumberGenerator generator = new RandomNumberGeneratorImpl();
+
+    public <T> T choice(List<T> options) {
+        if (options.size() == 0) return null;
+        int idx = generator.nextInt() % options.size();
+        return options.get(idx);
+    }
+}

junit-examples/src/main/java/ch11/SpyExample.java

+package ch11;
+
+import java.util.logging.Logger;
+
+/**
+ * リスト11.20
+ * リスト11.31 ロガーを扱うクラス
+ * @author shuji.w6e
+ */
+public class SpyExample {
+    
+    Logger logger = Logger.getLogger(SpyExample.class.getName());
+    
+    public void doSomething() {
+        logger.info("doSomething");
+    }
+}

junit-examples/src/main/java/ch11/User.java

+package ch11;
+
+public class User {
+
+}

junit-examples/src/main/java/ch11/UserDao.java

+package ch11;
+
+
+/**
+ * リスト11.17
+ * @author shuji.w6e
+ */
+public interface UserDao {
+    
+    User find(String userId) throws UserNotFoundException;
+}

junit-examples/src/main/java/ch11/UserNotFoundException.java

+package ch11;
+
+public class UserNotFoundException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public UserNotFoundException(String message) {
+        super(message);
+    }
+
+}

junit-examples/src/main/java/ch11/withclass/DateFactory.java

+package ch11.withclass;
+
+import java.util.Date;
+
+/**
+ * リスト11.5
+ * @author shuji.w6e
+ */
+public class DateFactory {
+
+    Date newDate() {
+        return new Date();
+    }
+}

junit-examples/src/main/java/ch11/withclass/DelegateObjectExample.java

+package ch11.withclass;
+
+import java.util.Date;
+
+/**
+ * リスト11.6
+ * @author shuji.w6e
+ */
+public class DelegateObjectExample {
+
+    DateFactory dateFactory = new DateFactory();
+    Date date = new Date();
+    
+    public void doSomething() {
+        this.date = dateFactory.newDate();
+        // なんらかの処理(省略)
+    }
+}

junit-examples/src/main/java/ch11/withinterface/DateFactory.java

+package ch11.withinterface;
+
+import java.util.Date;
+
+/**
+ * リスト11.7
+ * @author shuji.w6e
+ */
+public interface DateFactory {
+
+    Date newDate();
+}

junit-examples/src/main/java/ch11/withinterface/DateFactoryImpl.java

+package ch11.withinterface;
+
+import java.util.Date;
+
+/**
+ * リスト11.8
+ * @author shuji.w6e
+ */
+public class DateFactoryImpl implements DateFactory {
+    @Override
+    public Date newDate() {
+        return new Date();
+    }
+}

junit-examples/src/main/java/ch11/withinterface/DelegateObjectExample.java

+package ch11.withinterface;
+
+import java.util.Date;
+
+/**
+ * リスト11.9
+ * @author shuji.w6e
+ */
+public class DelegateObjectExample {
+
+    DateFactory dateFactory = new DateFactoryImpl();
+    Date date = new Date();
+    
+    public void doSomething() {
+        this.date = dateFactory.newDate();
+        // なんらかの処理(省略)
+    }
+}

junit-examples/src/test/java/ch11/DateDependencyExampleTest.java

+package ch11;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Date;
+
+import org.junit.Test;
+
+/**
+ * リスト11.2
+ * @author shuji.w6e
+ */
+public class DateDependencyExampleTest {
+
+    @Test
+    public void doSomethingでdateに現在時刻が設定される() throws Exception {
+        DateDependencyExample sut = new DateDependencyExample();
+        sut.doSomething();
+        // このアサーションは実行タイミングによって成功にも失敗にもなる
+        assertThat(sut.date, is(new Date()));
+    }
+
+}

junit-examples/src/test/java/ch11/MethodExtractExampleTest.java

+package ch11;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Date;
+
+import org.junit.Test;
+
+/**
+ * リスト11.4
+ * @author shuji.w6e
+ */
+public class MethodExtractExampleTest {
+
+    @Test
+    public void doSomethingを実行するとdateに現在時刻が設定される() throws Exception {
+        final Date current = new Date();
+        MethodExtractExample sut = new MethodExtractExample() {
+            @Override
+            Date newDate() {
+                return current;
+            }
+        };
+        sut.doSomething();
+        assertThat(sut.date, is(sameInstance(current)));
+    }
+}

junit-examples/src/test/java/ch11/MockitoExamples.java

+package ch11;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * リスト11.23 モックオブジェクトに定義されたメソッドの戻り値
+ * リスト11.24 スタブメソッドの設定
+ * リスト11.25 例外を送出するスタブメソッド
+ * リスト11.26 void型を返すスタブメソッド
+ * リスト11.27 任意の整数に対するスタブメソッド
+ * リスト11.28 スタブメソッドの検証
+ * リスト11.29 部分的なモックオブジェクト
+ * @author shuji.w6e
+ */
+@SuppressWarnings("unchecked")
+public class MockitoExamples {
+
+    @Test
+    public void モックオブジェクトに定義されたメソッドの戻り値() throws Exception {
+        // モックオブジェクトの作成
+        List<String> mock = mock(List.class);
+        assertThat(mock.get(0), is(nullValue()));
+        assertThat(mock.add("Hello"), is(false));
+    }
+
+    @Test
+    public void スタブメソッドの設定() throws Exception {
+        List<String> stub = mock(List.class); // スタブオブジェクトの作成
+        when(stub.get(0)).thenReturn("Hello"); // スタブの設定
+        assertThat(stub.get(0), is("Hello")); // 検証
+    }
+
+    @Test(expected = IndexOutOfBoundsException.class)
+    public void 例外を送出するスタブメソッド() throws Exception {
+        List<String> stub = mock(List.class);
+        when(stub.get(0)).thenReturn("Hello");
+        when(stub.get(1)).thenReturn("World");
+        when(stub.get(2)).thenThrow(new IndexOutOfBoundsException());
+        stub.get(2); // 例外が送出される
+    }
+
+    @Test(expected = RuntimeException.class)
+    public void 戻り値がvoid型のメソッド() throws Exception {
+        List<String> stub = mock(List.class);
+        doThrow(new RuntimeException()).when(stub).clear();
+        stub.clear(); // 例外が送出される
+    }
+
+    @Test
+    public void 任意の整数に対するスタブメソッド() throws Exception {
+        List<String> stub = mock(List.class);
+        when(stub.get(anyInt())).thenReturn("Hello");
+        assertThat(stub.get(0), is("Hello"));
+        assertThat(stub.get(1), is("Hello"));
+        assertThat(stub.get(999), is("Hello"));
+    }
+
+    @Test
+    public void モックの検証() throws Exception {
+        List<String> mock = mock(List.class);
+        mock.clear();
+        mock.add("Hello");
+        mock.add("Hello");
+        verify(mock).clear();
+        verify(mock, times(2)).add("Hello");
+        verify(mock, never()).add("World");
+    }
+
+    @Test
+    public void 部分的なモックオブジェクト() throws Exception {
+        List<String> list = new java.util.LinkedList<String>();
+        List<String> spy = spy(list);
+        doReturn("Mockito").when(spy).get(1);
+        spy.add("Hello");
+        spy.add("World");
+        verify(spy).add("Hello");
+        verify(spy).add("World");
+        assertThat(spy.get(0), is("Hello"));
+        assertThat(spy.get(1), is("Mockito"));
+    }
+
+}

junit-examples/src/test/java/ch11/RandomNumberGeneratorFixedResultStub.java

+package ch11;
+
+/**
+ * リスト11.13
+ * @author shuji.w6e
+ */
+public class RandomNumberGeneratorFixedResultStub implements RandomNumberGenerator {
+
+    @Override
+    public int nextInt() {
+        return 1;
+    }
+
+}

junit-examples/src/test/java/ch11/RandomNumberGeneratorStub.java

+package ch11;
+
+/**
+ * リスト11.16
+ * @author shuji.w6e
+ */
+public class RandomNumberGeneratorStub implements RandomNumberGenerator {
+
+    private final int num;
+
+    public RandomNumberGeneratorStub(int num) {
+        this.num = num;
+    }
+
+    @Override
+    public int nextInt() {
+        return num;
+    }
+
+}

junit-examples/src/test/java/ch11/RandomsMockTest.java

+package ch11;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.junit.Test;
+
+/**
+ * リスト11.19
+ * @author shuji.w6e
+ */
+public class RandomsMockTest {
+
+    @Test
+    public void choiceでAを返す() throws Exception {
+        List<String> options = new ArrayList<String>();
+        options.add("A");
+        options.add("B");
+        Randoms sut = new Randoms();
+        // モックの設定
+        final AtomicBoolean isCallNextIntMethod = new AtomicBoolean(false);
+        sut.generator = new RandomNumberGenerator() {
+            @Override
+            public int nextInt() {
+                isCallNextIntMethod.set(true);
+                return 0;
+            }
+        };
+        assertThat(sut.choice(options), is("A"));
+        assertThat(isCallNextIntMethod.get(), is(true));
+    }
+}

junit-examples/src/test/java/ch11/RandomsTest.java

+package ch11;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * リスト11.15
+ * @author shuji.w6e
+ */
+public class RandomsTest {
+
+    @Test
+    public void choiceでAを返す() throws Exception {
+        List<String> options = new ArrayList<String>();
+        options.add("A");
+        options.add("B");
+        Randoms sut = new Randoms();
+        // スタブの設定
+        sut.generator = new RandomNumberGenerator() {
+            @Override
+            public int nextInt() {
+                return 0;
+            }
+        };
+        assertThat(sut.choice(options), is("A"));
+    }
+
+    @Test
+    public void choiceでBを返す() throws Exception {
+        List<String> options = new ArrayList<String>();
+        options.add("A");
+        options.add("B");
+        Randoms sut = new Randoms();
+        // スタブの設定
+        sut.generator = new RandomNumberGenerator() {
+            @Override
+            public int nextInt() {
+                return 1;
+            }
+        };
+        assertThat(sut.choice(options), is("B"));
+    }
+
+}

junit-examples/src/test/java/ch11/SpyExampleTest.java

+package ch11;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
+
+import java.util.logging.Logger;
+
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+/**
+ * リスト11.22 ロガーオブジェクトにログを記録していることを検証するテスト
+ * リスト11.30 スパイオブジェクトの作成
+ * リスト11.32 ロガーのスパイオブジェクトの利用
+ * @author shuji.w6e
+ */
+public class SpyExampleTest {
+
+    @Test
+    public void SpyLoggerを利用したテスト() {
+        SpyExample sut = new SpyExample();
+        SpyLogger spy = new SpyLogger(sut.logger);
+        sut.logger = spy;
+        sut.doSomething();
+        assertThat(spy.log.toString(), is("doSomething"));
+    }
+
+    @Test
+    public void Mockitoのspyを使ったテスト() throws Exception {
+        // SetUp
+        SpyExample sut = new SpyExample();
+        Logger spy = spy(sut.logger);
+        final StringBuilder infoLog = new StringBuilder();
+        doAnswer(new Answer<Void>() {
+
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                infoLog.append(invocation.getArguments()[0]);
+                invocation.callRealMethod();
+                return null;
+            }
+        }).when(spy).info(anyString());
+        sut.logger = spy;
+        // Exercise
+        sut.doSomething();
+        // Verify
+        assertThat(infoLog.toString(), is("doSomething"));
+    }
+}

junit-examples/src/test/java/ch11/SpyLogger.java

+package ch11;
+
+import java.util.logging.Logger;
+
+/**
+ * リスト11.21
+ * @author shuji.w6e
+ */
+public class SpyLogger extends Logger {
+
+    final Logger base;
+    final StringBuffer log = new StringBuffer();
+
+    public SpyLogger(Logger base) {
+        super(base.getName(), base.getResourceBundleName());
+        this.base = base;
+    }
+
+    // infoのみ対応
+    @Override
+    public void info(String msg) {
+        log.append(msg);
+        base.info(msg);
+    }
+
+}

junit-examples/src/test/java/ch11/UserDaoStub.java

+package ch11;
+
+
+/**
+ * リスト11.18
+ * @author shuji.w6e
+ */
+public class UserDaoStub implements UserDao {
+
+    @Override
+    public User find(String userId) throws UserNotFoundException {
+        throw new UserNotFoundException("connection error");
+    }
+
+}

junit-examples/src/test/java/ch11/withclass/DelegateObjectExampleTest.java

+package ch11.withclass;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Date;
+
+import org.junit.Test;
+
+/**
+ * @author shuji.w6e
+ */
+public class DelegateObjectExampleTest {
+
+    @Test
+    public void doSomethingを実行するとdateに現在時刻が設定される() throws Exception {
+        final Date current = new Date();
+        DelegateObjectExample sut = new DelegateObjectExample();
+        sut.dateFactory = new DateFactory() {
+            @Override
+            public Date newDate() {
+                return current;
+            }
+        };
+        sut.doSomething();
+        assertThat(sut.date, is(sameInstance(current)));
+    }
+
+}

junit-examples/src/test/java/ch11/withinterface/DelegateObjectExampleTest.java

+package ch11.withinterface;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Date;
+
+import org.junit.Test;
+
+/**
+ * リスト11.10
+ * @author shuji.w6e
+ */
+public class DelegateObjectExampleTest {
+
+    @Test
+    public void doSomethingを実行するとdateに現在時刻が設定される() throws Exception {
+        final Date current = new Date();
+        DelegateObjectExample sut = new DelegateObjectExample();
+        sut.dateFactory = new DateFactory() {
+            @Override
+            public Date newDate() {
+                return current;
+            }
+        };
+        sut.doSomething();
+        assertThat(sut.date, is(sameInstance(current)));
+    }
+
+}