模拟出任何python类实例上的方法 [英] Mocking out methods on any instance of a python class

查看:62
本文介绍了模拟出任何python类实例上的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在生产代码中模拟某个类的任何实例的方法,以便于测试. Python中是否有任何库可以简化此操作?

I want to mock out methods on any instance of some class in the production code in order to facilitate testing. Is there any library in Python which could facilitate this?

基本上,我想执行以下操作,但是在Python中(以下代码是Ruby,使用Mocha库):

Basically, I want to do the following, but in Python (the following code is Ruby, using the Mocha library):

  def test_stubbing_an_instance_method_on_all_instances_of_a_class
    Product.any_instance.stubs(:name).returns('stubbed_name')
    assert_equal 'stubbed_name', SomeClassThatUsesProduct.get_new_product_name
  end

从上面需要注意的重要一点是,我需要在类级别上对其进行模拟,因为实际上我需要对由我正在测试的事物创建的实例上的方法进行模拟.

The important thing to note from above is that I need to mock it out on the class level, since I'm actually need to mock out methods on an instance created by the thing I'm testing.

用例:

我有一个类QueryMaker,它在RemoteAPI的实例上调用方法.我想模拟RemoteAPI.get_data_from_remote_server方法以返回一些常量.我如何在测试中执行此操作,而不必在RemoteAPI代码中放入特殊情况以检查其运行在什么环境中.

I have a class QueryMaker which calls a method on an instance of RemoteAPI. I want to mock out the RemoteAPI.get_data_from_remote_server method to return some constant. How do I do this inside a test without having to put a special case within the RemoteAPI code to check for what environment it's running in.

我想要采取的行动的示例:

Example of what I wanted in action:

# a.py
class A(object):
    def foo(self):
        return "A's foo"

# b.py
from a import A

class B(object):
    def bar(self):
        x = A()
        return x.foo()

# test.py
from a import A
from b import B

def new_foo(self):
    return "New foo"

A.foo = new_foo

y = B()
if y.bar() == "New foo":
    print "Success!"

推荐答案

最简单的方法可能是使用类方法.您确实应该使用实例方法,但是创建它们很麻烦,而内置函数可以创建类方法.使用类方法,您的存根将获得对类(而不是实例)的引用作为第一个参数,但是由于它是存根,因此这可能无关紧要.所以:

Easiest way is probably to use a class method. You really should use an instance method, but it's a pain to create those, whereas there's a built-in function that creates a class method. With a class method, your stub will get a reference to the class (rather than the instance) as the first argument, but since it's a stub this probably doesn't matter. So:

Product.name = classmethod(lambda cls: "stubbed_name")

请注意,lambda的签名必须与您要替换的方法的签名匹配.而且,当然,由于Python(例如Ruby)是一种动态语言,因此无法保证有人在您获得实例之前不会将您的存根方法切换为其他方法,尽管我希望您很快就会知道如果发生这种情况.

Note that the signature of the lambda must match the signature of the method you're replacing. Also, of course, since Python (like Ruby) is a dynamic language, there is no guarantee that someone won't switch out your stubbed method for something else before you get your hands on the instance, though I expect you will know pretty quickly if that happens.

在进一步调查中,您可以省略classmethod():

On further investigation, you can leave out the classmethod():

Product.name = lambda self: "stubbed_name"

我试图尽可能地保留原始方法的行为,但实际上似乎并没有必要(并且也没有按照我希望的那样保留行为).

I was trying to preserve the original method's behavior as closely as possible, but it looks like it's not actually necessary (and doesn't preserve the behavior as I'd hoped, anyhow).

这篇关于模拟出任何python类实例上的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆