如何为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中,正确的做法是什么呢?
1 个回答
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)
然后在测试结束后撤销这个“猴子补丁”(比如如果在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
,并传入你想用的假函数,就可以适当地准备这个实例!