我有一个方法,它需要另一个类的类方法
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中使用正确的方法是什么?
答案 0 :(得分: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)
然后撤消此猴子修补(例如,如果在tearDown
中完成修补,则使用setUp
方法)
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
和你想要使用的假函数来准备该实例!