开发者

How to write a stub for a classmethod in Python

开发者 https://www.devze.com 2022-12-10 04:00 出处:网络
I have a method which calls for a classmethod of another class def get_interface_params_by_mac(self, host, mac_unified):

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!

0

精彩评论

暂无评论...
验证码 换一张
取 消