2012-11-13 150 views
3

這個問題測試裝修裝飾是後續this brilliant answer關於裝飾在Python:蟒蛇通過模擬

我使用給定的「片段做任何裝飾一般接受任何說法」。

然後,我有這樣的(這裏的簡化)裝飾:

@decorator_with_args 
def has_permission_from_kwarg(func, *args, **kwargs): 
    """Decorator to check simple access/view rights by the kwarg.""" 
    def wrapper(*args_1, **kwargs_1): 
     if 'kwarg' in kwargs_1: 
      kwarg = kwargs_1['kwarg'] 
     else: 
      raise HTTP403Error() 

     return func(*args_1, **kwargs_1) 

    return wrapper 
  1. 與這個裝飾,沒有問題它的工作非常好工作。
  2. 測試一個類似的裝飾,不需要絕對的kwargs,相同的結果。
  3. 但測試這個裝飾用下面的模擬不起作用:

    def test_can_access_kwarg(self): 
        """Test simple permission decorator.""" 
        func = Mock(return_value='OK') 
        decorated_func = has_permission_from_slug()(func(kwarg=self.kwarg)) 
        # It will raise at the following line, whereas the kwarg is provided... 
        response = decorated_func() 
        self.assertTrue(func.called) 
        self.assertEqual(response, 'OK') 
    

它返回我時,我沒有「kwarg」關鍵字參數我提出的例外...

有誰有一個線索如何(用嘲諷將是可取的),這樣的裝飾由需要訪問的傳遞給函數的關鍵字參數彼此裝飾裝潢測試?

回答

2
decorated_func = has_permission_from_slug()(func(kwarg=self.kwarg)) 

這將:

  1. 執行func(kwarg=self.kwarg)
  2. 生成實際裝飾的一個實例。
  3. 呼叫上FUNC- 呼叫(即,結果)的結果的裝飾。
  4. 返回然後將稍後嘗試撥打步驟3(這將失敗)結果包裝。

    響應= decorated_func()

這將接着調用返回的包裝不帶參數,所以**kwargs_1是空的。另外,如果你包裝器不會提高在這種情況下的例外,的func(..)後續調用會因爲func(原來的)返回的值可能不是調用(見上文)拋出異常。

什麼你可能想要做的,而不是,或至少你的裝飾支持什麼,這就是:

decorated_func = has_permission_from_kwarg()(func) 
response = decorated_func(kwarg=self.kwarg) 

或者,如果你想通過你的kwarg在裝飾這樣的:

decorated_func = has_permission_from_kwarg(kwarg=self.kwarg)(func) 
response = decorated_func() 

然後,你需要調整或裝飾在檢查實際使用kwargs,而不是kwargs_1(後者的參數傳遞給裝飾功能)。


我測試你原來的裝飾定義(沒有變化),並在鏈接的答案用下面的代碼中定義的decorator_with_args

class HTTP403Error (Exception): 
    pass 

def func (*args, **kwargs): 
    print('func {}; {}'.format(args, kwargs)) 

my_kwarg = 'foo' 
decorated_func = has_permission_from_kwarg()(func) 
decorated_func(kwarg=my_kwarg) 
decorated_func(not_kwarg=my_kwarg) 

正如預期的那樣,我得到func(); {'kwarg': 'foo'}打印的第一次調用,第二次調用HTTP403異常。

+0

嗨戳,謝謝你的回答! 我應該在之前說過,但是當然我也試過你的建議。不幸的是: 第一個樣本失敗,因爲'response = decorated_func(kwarg = self.kwarg)'返回「TypeError:'str'對象不可調用」 第二個工程,但不適合我原來的範圍,我想測試一個在我的代碼中使用kwargs_1的裝飾器。 – Rmatt

+0

在最後一個代碼示例中有一個小錯誤,現在也可以使用。第一個解決方案雖然工作。 – poke

+0

好,但第二個例子仍然不符合我的目的。第一個仍然失敗。它做的工作超越了kwarg檢查,但失敗了,返回func(* args_1,** kwargs_1)' – Rmatt