I have a method which calls for a classmethod of another class
def get_interface_params_by_mac(self, host, mac_unified):
lines = RemoteCommand.remote_command(host, cls.IFCONFIG)
...
class RemoteCommand(object):
@clas开发者_StackOverflow中文版smethod
def remote_command(cls, host, cmd, sh = None):
...
I'm going to write a unit test for get_interface_params_by_mac method, in which I'd like to change an implementation of remote_command (I think it calls stub - fix me if I wrong)
What the right way to do this in Python?
Your unit-test code (maybe in its setUp
method, if this is needed across several test methods and thus qualifies as a fixture) should do:
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)
and then undo this monkey-patching (e.g. in the tearDown
method if the patching is done in setUp
) by
somemodule.RemoteCommand.remote_command = self.save_remote_command
It's not always necessary to put things back after a test, but it's good general practice.
A more elegant approach would be to design your code for testability via the Dependency Injection (DI) pattern:
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 buys you a lot of flexibility (testability-wise, but also in many other contexts) at very little cost, which makes it one of my favorite design patterns (I'd much rather avoid monkey patching wherever I possibly can). Of course, if you design your code under test to use DI, all you need to do in your test is appropriately prepare that instance by calling the instance's set_remote_command_function
with whatever fake-function you want to use!
精彩评论