2015-12-09 41 views
4

解决方法:如何在python中模拟/修补装饰器?

我无法修补装饰器,仍然可以访问包装的功能。但解决方法我测试包裹在一个装饰功能为以下几点:

def un_some_method(self): 
... 

some_method = some_var.some_decorator('somestring')(un_some_method)  

这仍然装饰我的功能,但让我访问功能,如果我想对它进行测试,在其他地方重复使用它...

这就是问题所在:

我有一个模块,其中有一类吧,和实例,从而暴露出装饰类变量。

然后我的模块内的类中,我使用这个变量与我的类的实例,并在我的课的装修方法......要清楚,让我们看看一些代码:

some_var = ClassX() 

class SomeClass(object): 

    @some_var.some_decorator('somestring') 
    def some_method(self): 
     ... 

在我的测试中,我想内some_method测试代码,我不关心装饰...虽然我试图模仿装饰出来是没有用的......下面是一些事情我想:

@patch('path_to_classx.ClassX.some_decorator') 
@patch('path_to_someclassmodule.some_var') 
@patch('path_to_someclassmodule.ClassX') 

无上述尝试阻止了该功能被装饰...任何ide为什么?

+1

这是一个非常有趣的问题,但我只是好奇:如果装饰器是代码的一部分,为什么要禁用它? –

+0

,因为装饰器中的代码在其他地方被测试过,为了保持测试单元的概念,让我的函数的结果为不同的结果填充装饰器似乎破坏了这个规则......再加上如果装饰器破坏,它会打破我使用装饰器的测试,这可能是误导? – Bodao

+1

我明白你不希望你的函数被一个潜在的破坏装饰器所迷惑。但是被测试的功能必须在装饰状态下正常运行,不是吗?如果那是真的,那么用我设计的装饰器来测试它是有意义的。也许你可以设计一组条件来隔离装饰器和被测试函数的故障?我看到它的方式,如果测试失败了,无论原因如何,都必须重构。我从来没有嘲笑一个装饰者,因为你是当我尝试一个测试案例来回答你的问题,我无法让它工作... –

回答

2

一种选择是在实例化之后修补some_var,用标识函数替换some_decorator,以便装饰的方法保持不变。

import mock 
class ClassX(object): 
    def some_decorator(self, f): 
     def g(*args, **kwargs): 
      print("Hello") 
      return f(*args, **kwargs) 
     return g 

some_var = ClassX() 

with mock.patch.object(some_var, 'some_decorator', side_effect=lambda f: f): 

    class SomeClass(object): 
     @some_var.some_decorator 
     def some_method(self): 
      print "World" 


SomeClass().some_method() 
+0

这听起来做的伎俩莫名其妙,但现在我得到一个错误'对象不可调用“时,装饰器被触发,不知道如果我做错了什么,让你张贴和谢谢! – Bodao

+0

好吧,这工作显然,但问题是,我的装饰器接受一个参数,它是一个字符串,所以lambda将返回字符串,而不是功能......任何想法? 示例:@ some_var.some_decorator('somestring') – Bodao

+0

这是您需要在原始问题中包含的那种细节。 – chepner