2009-11-05 61 views
0

我有要求另一个类如何写一个存根在Python

def get_interface_params_by_mac(self, host, mac_unified): 
     lines = RemoteCommand.remote_command(host, cls.IFCONFIG) 

的类方法的方法...

class RemoteCommand(object): 

    @classmethod 
    def remote_command(cls, host, cmd, sh = None): 
    ... 

我打算写一单元一类方法测试get_interface_params_by_mac方法,其中,我想改变remote_command的实现(我想它调用存根 - 如果我错了整我)

在Python中做到这一点的正确方法是什么?

回答

7

你的单元测试的代码(也许在其setUp方法中,如果这是需要在几个试验方法和由此有资格作为夹具)应该做的:

def fake_command(cls, host, cmd, sh=None): 
    pass # whatever you want in here 
self.save_remote_command = somemodule.RemoteCommand.remote_command 
somemodule.RemoteCommand.remote_command = classmethod(fake_command) 

,然后撤消此猴修补(例如在)由

somemodule.RemoteCommand.remote_command = self.save_remote_command 

tearDown方法,如果修补在setUp做这并不总是必要的测试后,把东西回来,但它是很好的一般做法。

一个更优雅的方法是通过依赖注入来设计您的可测试性的代码(DI)模式:

def __init__(self, ...): 
    ... 
    self.remote_command = RemoteCommand.remote_command 
    ... 

def set_remote_command_function(self, thefunction): 
    self.remote_command = thefunction 

def get_interface_params_by_mac(self, host, mac_unified): 
     lines = self.remote_command(host, cls.IFCONFIG) 

DI买你一个很大的灵活性(可测试性,明智的,而且在许多其他情况下),这使得它成为我最喜欢的设计模式之一(我宁愿尽可能避免使用猴子修补)。当然,如果你在测试中设计你的代码来使用DI,那么在你的测试中你需要做的所有事情都是通过调用实例的set_remote_command_function以及你想使用的任何假函数来准备好这个实例。

+0

谢谢,亚历克斯。这正是我需要的。我还想读一些关于DI的东西。你能给我一个链接吗? – legesh 2009-11-05 20:15:25

+0

另一个问题...我真的需要一个方法set_remote_command_function?据我所知,我可以写这样的东西:myobj.remote_command = RemoteCommand.remote_command – legesh 2009-11-05 20:40:40

+0

@legesh,对于DI,见http://www.aleax.it/yt_pydi.pdf我的演示文稿的PDF。不,你不一定需要一个setter方法,直接的属性分配(如果你需要在这样的任务上做一些记录,可能通过一个属性)也可以工作。 – 2009-11-06 04:24:18