2014-03-05 49 views
6

我想測試一個簡單的裝飾我寫道:蟒蛇模擬:@wraps(F)的問題

它看起來像這樣:

#utilities.py 
import other_module 
def decor(f): 
    @wraps(f) 
    def wrapper(*args, **kwds): 
      other_module.startdoingsomething() 
     try: 
      return f(*args, **kwds) 
     finally: 
      other_module.enddoingsomething() 
    return wrapper 

然後,我用它測試的python-模擬:

#test_utilities.py 
def test_decor(self): 
    mock_func = Mock() 
    decorated_func = self.utilities.decor(mock_func) 
    decorated_func(1,2,3) 
    self.assertTrue(self.other_module.startdoingsomething.called) 
    self.assertTrue(self.other_module.enddoingsomething.called) 
    mock_func.assert_called_with(1,2,3) 

但它踢回:

Traceback (most recent call last): 
    File "test_utilities.py", line 25, in test_decor 
    decorated_func = Mock(wraps=self.utilities.decor(mock_func)) 
    File "utilities.py", line 35, in decor 
    @wraps(f) 
    File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper 
    setattr(wrapper, attr, getattr(wrapped, attr)) 
    File "/usr/local/lib/python2.7/dist-packages/mock.py", line 660, in __getattr__ 
    raise AttributeError(name) 
AttributeError: __name__ 

我知道functools.wraps()只是一個輔助包裝。所以如果我把它拿出來進行測試。

我可以通過functools.wraps()來玩Mock嗎?

的Python 2.7.3

回答

7

只要給你的模擬那個屬性:

mock_func.__name__ = 'foo' 

這是真的。

演示:

>>> from functools import wraps 
>>> from mock import Mock 
>>> def decor(f): 
...  @wraps(f) 
...  def wrapper(*args, **kwds): 
...   return f(*args, **kwds) 
...  return wrapper 
... 
>>> mock_func = Mock() 
>>> decor(mock_func) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in decor 
    File ".../opt/lib/python2.7/functools.py", line 33, in update_wrapper 
    setattr(wrapper, attr, getattr(wrapped, attr)) 
    File ".../lib/python2.7/site-packages/mock.py", line 660, in __getattr__ 
    raise AttributeError(name) 
AttributeError: __name__ 
>>> mock_func.__name__ = 'foo' 
>>> decor(mock_func) 
<function foo at 0x10c4321b8> 

設置__name__是完全沒有問題; @wraps裝飾器只是簡單地將__name__屬性複製到包裝器,並且在函數對象上,該屬性通常設置爲字符串值。它是函數的可寫屬性,無論如何,只要你使用字符串function.__name__可以設置爲任何值。

+0

是的,這就是我所做的。我不確定是否有嚴重的後果。如存在「適當」的價值。但測試通過了,所以我想沒有問題?! 似乎它在這裏被提出並關閉:https://code.google.com/p/mock/issues/detail?id=67 – powlo

+0

@paulus_almighty:任何字符串值都可以。任何你可以在'function .__ name__'上使用的東西,只要類型是'str'就可以。 –

+0

謝謝它可以很好地工作。 –