2011-07-13 55 views
5

我正在爲我的grails應用程序編寫單元測試,並且我意識到我並不真正瞭解用於聲明對象是否是適當對象的正確方法。在單元測試中比較對象的正確方法

例如,假設本次測試:

void testExampleTest() { 
    mockSession.person = new Person(firstName:'John', lastName:'Doe', middleInitial:'E') 
    def model = controller.testMethod() 
    ...assertions... 
} 

def testMethod = { 
    Person currPerson = session.getAttribute("person") 
    render(view:'view',model:[person:currPerson] 
} 

我應該如何確保我加入會話的人對象正在正確的模型通過呢?它是足夠使用

assertEquals(person,model['person']) 

還是因爲我自己注入對象到會話並使其使用起來更感

assertEquals(person.firstName, model['person'].firstName) 
assertEquals(person.lastName, model['person'].lastName) 
assertequals(person.middleName, model['person'].middleName) 

這在我看來,第一種方式應該只要足夠的對象有一個正確定義的equals方法,但我只想看看傳統方式是什麼。

謝謝

回答

2

不同性質的比較需要在每次測試中重複 - 所以這是一個很好的舊代碼重複,a test smell described in XUnitPatterns。最好有一個合適的equals()

當然,您可以在運行時添加實用程序方法personEquals()甚至覆蓋Person.equals()。對於嘲笑課,你可能不得不這樣做。如果可能,我個人堅持使用較短的代碼,這只是一個assertEquals()

2

有趣的是,我和一位同事今天進行了類似的討論。我們的結論是,

比較費力的按屬性進行比較的一個優點是,它報告了一個特定的差異,而不僅僅是「不,它們不等於」,這可能很方便。

此外,我們沒有控制某些類,其中一些缺乏等號方法。

我們打算調查是否有可能使用反射來實現比較器,從而消除一些乏味。

+0

另請參閱我的回答:commons-beans庫使使用基於反射的訪問變得簡單,可以使用基於反射的訪問來構建多屬性斷言方法。 –

1

如果等於正確定義你是對的。問題是,如果equals被正確定義(意味着它按照您期望的方式行事),那麼您可能必須首先進行單元測試。

如果您爲Person類創建模型,這可能會變得更加困難。在這種情況下,你不關心equals是否正常工作,因爲你只想檢查是否正確設置/訪問了某些屬性。這就是爲什麼我喜歡在可能和必要時檢查原始值。我發現它使測試也更具描述性(儘管它可能變得相當冗長)。

0

正如你所寫,如果測試數據有一個適當的等號方法,你可以使用它。這裏的「適當」意味着它測試你想要測試的屬性。

我經常使用只比較其ID屬性的數據庫實體。有了這些對象,我需要分別測試每個屬性以查看它們是否相等。我寫了一個小幫手,讓我寫一個斷言許多特性,如:

assertEqualProperties(person, model['person'], "firstName", "lastName", "middleName"); 

這個輔助方法使用反射來訪問屬性(不直接,我調用公共豆庫)。在Groovy中,肯定有一個不需要明確反映的語法。該方法報告第一個不等於屬性作爲測試失敗。

0

Grails中的每個對象是可序列化的,因此你可以使用自己的XML序列化比較兩種:

public void compareXML(Object a, Object b) 
    ByteArrayOutputStream aBaos = new ByteArrayOutputStream(); 
    XMLEncoder aEncoder = new XMLEncoder(aBaos); 
    aEncoder.writeObject(a); 
    aEncoder.close(); 
    String xmlA = baos.toString(); 

    ByteArrayOutputStream bBaos = new ByteArrayOutputStream(); 
    XMLEncoder bEncoder = new XMLEncoder(bBaos); 
    bEncoder.writeObject(b); 
    bEncoder.close(); 
    String xmlB = bBaos.toString(); 

    assertEquals(xmlA, xmlB); 
} 

如果您在Eclipse正在努力,你會得到兩個XML字符串的偉大文本比較顯示所有的差異。

+0

Grails的GUnit在對象差異的文本表示方面做得更好。 –

1

在這個特定的實例中,測試各個屬性只是識別對象的特定實例的一種方式,它會覆蓋測試的含義。你特別關心,並應斷言那是什麼model['person']是完全相同的對象作爲你最初投入爲person

assertSame(person, model['person']) 

或者與Hamcrest,這使得整體更富於表現力的斷言:

assertThat(model['person'], sameInstance(person)) 
+0

事實上,如果測試對象預期會產生相同的實例,則應該測試該實例。 –

0

我使用assertSame()。比較字段是比所需的更多的工作 - 你嘲笑數據,所以只聲稱模擬值被正確地返回。

2

我已經發現,通過財產做財產是一個小更可靠,爲您提供了一些如何比較多一點點的精細控制,不好的一面是它的一點點更多的工作來建立和維護

相關問題