【问题标题】:How to write a stub for a classmethod in Python如何在 Python 中为类方法编写存根
【发布时间】:2009-11-05 18:15:34
【问题描述】:

我有一个方法调用另一个类的类方法

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 中执行此操作的正确方法是什么?

【问题讨论】:

    标签: python unit-testing


    【解决方案1】:

    您的单元测试代码(可能在其 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)
    

    然后撤消这个猴子补丁(例如,如果补丁在setUp中完成,则在tearDown方法中)

    somemodule.RemoteCommand.remote_command = self.save_remote_command 
    

    测试后并不总是需要把东西放回去,但这是一种很好的一般做法。

    更优雅的方法是通过依赖注入 (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 并使用您想要使用的任何假函数来适当地准备该实例!

    【讨论】:

    • 谢谢,亚历克斯。这正是我所需要的。我还想读一些关于 DI 的东西。能给个链接吗?
    • 另一个问题...我真的需要一个方法 set_remote_command_function 吗?据我了解,我可以这样写:myobj.remote_command = RemoteCommand.remote_command
    • @legesh,对于 DI,请参阅我在 aleax.it/yt_pydi.pdf 上的演示文稿的 PDF。不,您不一定需要 setter 方法,直接属性分配(如果您需要对此类分配进行一些簿记,可能通过属性)也可以工作。
    猜你喜欢
    • 2012-05-16
    • 2011-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多