unitTest

測試替身(2) - Dummy

首先登場的 就是最簡單的替身 也就是Dummy

當我們需要傳一個變數給某個method 所以需要一個跟signature一樣type的變數(因為java是strong type的language) 可是這個變數以後又不會用到 為了加速跟省記憶體空間 我們可以丟一個Dummy替身給這個method

比如說 我們想要測試People的getNumberOfPerson這個函式

public class People {
  private List<Person> persons;
  public void addPerson(Person p){
    persons.add(p);
  }
  public int getNumberOfPerson(){
    return persons.size();
  }
}

那你的測試可能原本長成這樣

public class PeopleTest{
  @Test
  public void testGetNumberOfPerson(){
    People people = new People();
    Person person1 = new Person("John Doe", 25, address1, phoneNumber1);
    Person person2 = new Person("Jane Doe", 23, address2, phoneNumber2);
    people.addPerson(person1);
    people.addPerson(person2);
    assertEquals(2, people.getNumberOfPerson())
  }
}

建一個Person可能開銷過大 而且很麻煩 況且Person並不是這個test的重點

這時候就要來個簡單的Dummy

public class DummyPerson extends Person {
   public DummyPerson() {}
}

這個class的目的就是要通過addPerson的型別限制 所以只要extends Person就可以

public class PeopleTestWithDummy{
  @Test
  public void testGetNumberOfPerson(){
    People people = new People();
    people.addPerson(new DummyPerson());
    people.addPerson(new DummyPerson());
    assertEquals(2, people.getNumberOfPerson())
  }
}

就是這麼簡單

Person的其他method呢

那Person的其他method 我們都全部不管 那如果getNumberOfPerson 呼叫了Person的method 我們無法知道 但這也不是這個unit test在乎的重點

但如果你真的想確保其他method不會被call 那就在DummyPerson裡面覆寫Person的其他method 然後都throw Exception就可以

Null

其實很多人在測試的時候 直接傳null進去 如果你要傳進去的function沒有nullCheck 這也是個可行的方式 但如果有nullCheck那還是只能用Dummy

Mockito

如果你寫的是java 你會很常看到Mickito 在Mockito裡面 如何生一個Dummy object呢?

public class PeopleTestWithDummy{
  @Test 
  public void testGetNumberOfPerson(){
    People people = new People();
    people.addPerson(mock(Person.class));
    people.addPerson(mock(Person.class));
    assertEquals(2, people.getNumberOfPerson())
  }
}

小心不要被這裡的mock搞混 他只是syntax是mock 但如果你只mock一個class但沒有給他任何預期的行為 他就是個dummy

我們是以用法來區分TestDoubles 不是syntax 因為很多framework不會為每一個TestDoubles都給一個constructor

都會把好幾個都參在一起用