2010-07-31 44 views
1

我正在寫一個小嘲笑類來做一些測試。解決嵌套屬性中的屬性錯誤

但是這個類需要支持具有嵌套屬性的想法。

這個例子應該提供一些見解的問題:

class Foo(object): 

    def __init__(self): 
     self.x = True 

從上面的類,我們可以有:

我知道我可以添加屬性回落至__getattr__,以避免AttributeError,但是如果我需要類似這樣的東西來生效:

f = Foo() 
f.x 
f.x.y 
f.x.y.z() 

我知道如果對象被稱爲f.x.y.z()要返回什麼,但我只需要找到一種方法來得到z()這是有道理的。

回答

3

你可以通過在每個屬性訪問上返回另一個「模擬任何東西」類的實例來「嘲笑任何東西」(如果你想讓.z()部分工作,它也必須是可調用的);-)。

如:

class MockAny(object): 

    # mock special methods by making them noops 
    def __init__(self, *a, **k): pass 

    # or returning fixed values 
    def __len__(self): return 0 

    # mock attributes: 
    def getattr(self, name): 
    return MockAny() 

    # make it callable, if you need to 
    def __call__(self, *a, **k): 
    return MockAny() 

的選擇,當然,是知道它是什麼,你嘲諷(通過反省,或者通過某種形式的「聲明性描述」,或者簡單地通過編碼嘲笑具體的事情;-)而不是採取全面的方法;但是,後者也是可行的,正如你在上面的(部分)例子中看到的那樣。我個人建議使用現有的模擬框架,如pymox,而不是重新發明這個特定的輪子(同樣,這樣的框架的源代碼可以比SO上的合理簡潔的響應更具啓發性,就像這樣; - )。

+0

就在當場Alex。我的錯誤是認爲,當我所需要的是傳遞Mock對象的另一個實例以匹配該屬性時,「構建」Mock對象以轉到x.y.z()是可以的。 我會使用一個模擬框架,但認爲對於我測試它的2個特定調用來說,實現一個單獨的模擬類會更清潔。 – alfredodeza 2010-07-31 11:19:12

1

如果你在你的單元測試中調用類似f.x.y.z()的東西,你可能會試圖測試太多。這些嵌套屬性中的每一個都應該由它們的特定類的單元測試覆蓋。

再看看您的Foo類,看看您是否可以在單元測試中測試自己的行爲。

也許不是你正在尋找的答案,但希望能從長遠來看有幫助。

+0

你是對的,除了在源代碼中調用f.x.y.z()而不是在unittest本身中。因此需要嘲笑它,以便在特定呼叫進行時返回預期行爲。 – alfredodeza 2010-07-31 11:09:52

+1

一般來說,'f'應該對'z()'甚至'y'都一無所知。這表明一個設計缺陷。 – Johnsyweb 2010-08-01 07:30:52