2013-07-16 73 views
5

我有一個數據源,我可以從中請求一個居住在任何國家的人的列表,以及一種從該數據源中檢索人並按字母順序排列他們的方法。我應該如何編寫單元測試以確保我的方法的排序部分正常工作?如何編寫單元測試來驗證函數對結果進行排序?

這是我的SUT的樣子:

class PeopleStuff { 

    public IData data; 

    public List<Person> getSortedPeopleForCountry(String countryName) { 
     List<Person> people = data.getPeopleForCountry(countryName); 

     Comparator nameComparator = new PersonNameComparator(); 
     Collections.sort(people, nameComparator); 

     return people; 
    } 

} 

這是我的單元測試是什麼樣子:

@Test public void testGetPeopleSortsByPeopleName() { 
    String COUNTRY = "Whatistan"; 

    // set up test (the 3 lines below are actually in a @Before setup method) 
    PeopleStuff peopleStuff = new PeopleStuff(); 
    IData mockData = createNiceMock(IData.class); 
    peopleStuff.data = mockData; 

    // set up data 
    List<PersonName> mockPeopleList = new ArrayList<PersonName>(); 
    mockPeopleList.add(new Person(COUNTRY, "A")); 
    mockPeopleList.add(new Person(COUNTRY, "D")); 
    mockPeopleList.add(new Person(COUNTRY, "B")); 
    mockPeopleList.add(new Person(COUNTRY, "C")); 

    when(mockData.getPeopleForCountry(COUNTRY)).thenReturn(mockPeopleList); 

    // exercise 
    List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY); 

    // assert 
    assertEquals("A", result.get(0).name); 
    assertEquals("B", result.get(1).name); 
    assertEquals("C", result.get(2).name); 
    assertEquals("D", result.get(3).name); 
} 

我需要知道的是,如果這樣我磕碰數據,運行測試並做出斷言是正確的,或者是否有更好的方法來做到這一點。

我的應用程序有很多方法來測試和很多自定義排序算法;我實施了所有測試,以使用4個我喜歡的測試值,in a "random" order,這是我在編寫測試時選擇的值。


我應該只測試比較器是否被調用?這對我來說並不合適,因爲我不知道他們是否需要正確的數據或在getSortedPeopleForCountry()內部的算法中正確的時間。我想檢測這樣的情況:

public List<Person> getSortedPeopleForCountry(String countryName) { 
    List<Person> people = data.getPeopleForCountry(countryName); 

    Comparator nameComparator = new PersonNameComparator(); 
    List<Person> sortedPeople = new ArrayList<Person>(people) 
    Collections.sort(sortedPeople, nameComparator); 

    return people; // oops! 
} 

我應該把它像這樣增加其使用真正的比較也證實他們被稱爲模擬比較器?

我在做對吧?

+0

我會對列表進行排序,然後開始比較其中的元素,以確保* current *元素與前一個元素具有相同或更大的*國家。 –

+0

@LuiggiMendoza我已經做到了,但我改變了主意。這在測試中添加了對'PersonNameComparator'的依賴。它採用了3行的「for」循環,這意味着測試中的額外算法,閱讀者必須理解這些算法才能理解測試。 –

+0

你讓它看起來像3行代碼很難理解......實際上,因爲我不使用easymock,所以上面的代碼對於我來說比使用簡單的for循環更難以理解。 'if'。 –

回答

2

我認爲你目前的測試非常好 - 測試是現實的,行使所有的代碼,並且你正在使用依賴注入模擬出數據源&來提供一個模擬數據源。在這個測試中有很多最佳實踐。

在你是否應該嘲笑比較(並因此使測試上testGetPeopleSortsByPeopleName一個純粹的單元測試),你一定會得到問題的兩種不同的意見在這裏:

  • 一個純粹會說,您的測試在技術上是一個集成測試,並且要進行適當的單元測試,您需要調整測試以使用模擬比較器,然後分別測試比較器。
  • 一位實用主義者會爭辯說,你的測試已經是高質量的了,並不重要,它不是嚴格意義上的單元測試。此外,將其分解爲兩個單獨的單元測試可能會使測試的可讀性降低 - 如果涉及模擬比較器,我想這將是上述測試的情況。

我個人的看法是,你應該離開,因爲它是,你有一個高品質的,可讀的測試演習的所有代碼,並有效地聲稱自己的要求其實是不是擔心有嚴格純更爲重要單元測試。

測試需要改進的唯一方法是測試方法的長度 - 我認爲一點方法提取可以幫助提高可讀性,並使測試方法更具表現力。我的目標是這樣的事情:

@Test public void testGetPeopleSortsByPeopleName() { 

    peopleStuff.data = buildMockDataSource(COUNTRY, "A", "D", "B", "C") 

    List<String> result = peopleStuff.getSortedPeopleForCountry(COUNTRY); 

    assertPersonList(result, "A", "B", "C", "D") 
} 

private IData buildMockDataSource(String country, String ... names) { 
    ... 
} 

private void assertPersonList(List<Person> people, String ... names) { 
    ... 
} 
+0

好吧,所以我就這樣做了,最後得到了大量的存根生成方法和列表斷言方法,但是結果很好,因爲我只是將它們全部放在測試幫助程序文件中。測試看起來非常整齊,易於維護。謝謝。 –

1

將排序邏輯與返回列表分開。所以我有getPeopleForCountry(String countryName)只返回一個列表,而排序列表將從getSortedPeopleForCountry(List)返回。這樣你就可以在排序前後測試它的工作原理。另外,如果這是你想要的,你可能想要重寫Equals()方法來比較名稱,但是之後你想要與其他屬性進行比較。這是你的電話。

+0

這是非常模糊的,它完全忽略了我寫我有Person對象的自定義比較器。而且,這個代碼只是我開發中的一個虛擬版本。問題是關於如何測試函數_looks like_我寫的例子是對給定的數據進行排序。 –

+0

它如何忽略你寫的比較器?您的比較器將在我的答案中使用getSortedPeopleForCountry(List T)...。無論如何,這是我的代碼。如果你有像testGetPeopleForCountryWhenNotSorting()這樣的測試方法,你可以測試其他的非排序方法不會測試。 – Mukus

0
ObjectA[] arr = objectAList.toArray(new ObjectA[objectAList.size()]); 
for (int i = 0; i < objectAList.size() - 1; i++) { 
     int j = i + 1; 
     assertTrue(arr[i].getDate().compareTo(arr[j].getDate()) >= 0); 
} 

這個代碼表示,其中的ArrayList contaning對象A的對象是通過實地日期降序排列的例子。我們正在檢查名單上的成員是否與他的前任有較小或相等的日期。

相關問題